实现HTTP 1.0服务器时出现问题

时间:2012-09-20 02:12:20

标签: c string http unix tokenize

我正在尝试使用 C 来实现一个简单的 HTTP 服务器

  1. 读取请求
  2. 检查是否是GET请求
  3. 从请求中读取网址
  4. 检查文件是否在服务器上并尝试打开它
  5. 我正在使用strtok进行字符串标记,我认为它会弄乱文件路径。 openfopen始终返回错误代码,无法打开任何文件。

    这是我的代码:

    /*
    ** 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 。这是输入GET /test.html时的输出:

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

1 个答案:

答案 0 :(得分:0)

尝试打开“test.html”而不是“\ test.html”