0

Cで単純なHTTPサーバーを実装しようとしています

  1. リクエストを読む
  2. GET リクエストかどうかを調べます
  3. リクエストから URL を読み取ります
  4. ファイルがサーバー上にあるかどうかを確認し、それを開こうとします

文字列のトークン化に使用strtokしていますが、ファイルパスが台無しになっていると思います。open常にエラー コードを返し、fopenファイルを開くことができません。

これが私のコードです:

/*
** parser.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MYPORT 3499    // the port users will be connecting to
#define BACKLOG 10     // how many pending connections queue will hold
#define MAXLEN 1024    //upper limit of the length of the string

int main(void)
{
    char input[MAXLEN]; //the line that is read from the client
    char * token1; //GET request
    char * token2; //filepath
    char tmpstring[MAXLEN]; //filesize
    int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd, file open on file_fd
    struct sockaddr_in my_addr;    // my address information
    struct sockaddr_in their_addr; // connector's address information
    int sin_size;
    int yes=1;
    int n; //the amount of read characters from the client

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    my_addr.sin_family = AF_INET;         // host byte order
    my_addr.sin_port = htons(MYPORT);     // short, network byte order
    my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
    memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct

    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    while(1) {  // main accept() loop
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
            perror("accept");
            continue;
        }

        printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
    n = readline(new_fd, input, MAXLEN); //n is the amount of read characters
    if (n == -1) {
        perror("Unable to read line");
    }

    //Check if it is a GET message
    token1 = strtok(input," ");
    if(strcmp(token1, "GET") != 0)
    {
        send(new_fd, "Bad request\n", 30, 0);
    }
    else
    {
        //Retrieve the file path
        token2 = strtok(NULL, " ");
        if(token2 == NULL)
        {
            send(new_fd, "File path not specified\n", 23, 0); //Check if filename is empty

        }
        send(new_fd, token2, strlen(token2), 0); //test
        printf("%s", token2);
        if(token2[0] == '/') //remove the initial slash    
            memmove(token2, token2 + 1, strlen(token2));
        //char * path = "test.html"; //test line
        //char * buff;
        //int len = sprintf(buff, "1: %d 2: %d\n", strlen(token1), strlen(token2));
        //send(new_fd, buff, len, 0);
        //Check if file is on the server
        if(open(token2, O_RDONLY) < 0) //Error opening file
        {
            if(errno == EACCES)            
                send(new_fd, "Access error\n", 30, 0);
            else
                send(new_fd, "Not existed\n", 30, 0);

        }
        else
        {

            FILE * requested_file = fopen(token2, "r");
            if(requested_file == NULL) //
            {
                send(new_fd, "Error in fopen\n", 30, 0);
            }
            else
            {
                send(new_fd, "File found\n", 30, 0); //successful
            }
            fseek(requested_file, 0, SEEK_END); // move to the end of the file
            int end=  ftell(requested_file);    // get the position of the end of file
            int stringlen = sprintf(tmpstring, "file size: %d\n", end);
            send(new_fd, tmpstring, stringlen, 0);
        }

    }

        close(new_fd); //close connection
    }

    return 0;
}

//helper function for recieving text
int readline(int fd, char *buf, int maxlen)
{
    int n, rc;
    char c;

    for (n = 1; n < maxlen; n++) {
    if ((rc = read(fd, &c, 1)) == 1) {
        *buf++ = c;
        if (c == '\n')
    break;
    } else if (rc == 0) {
        if (n == 1)
        return 0; // EOF, no data read
    else
        break; // EOF, read some data
        } else
    return -1; // error
    }

    *buf = '\0'; // null-terminate
    return n;
}

したがって、サーバーと同じフォルダーにtest.htmlを配置しています。次に、localhostポート 3499に telnet で接続します。これは、次のように入力したときの出力GET /test.htmlです。

/test.html
Not existed
rError in fopen
Connection closed by foreign host.
4

1 に答える 1

0

「\test.html」の代わりに「test.html」を開いてみてください

于 2012-11-24T05:16:06.820 に答える