2012-09-20 42 views
0

我想實現一個簡單的HTTP服務器Ç問題,同時實現HTTP 1.0服務器

  1. 讀取請求
  2. 檢查它是否是一個GET請求
  3. 讀取URL從請求
  4. 檢查文件是否在服務器上並試圖打開它

我正在使用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在同一文件夾作爲服務器。然後im telnet到本地主機端口3499。這是進入GET /test.html當輸出:

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

請直接納入的問題你的代碼。 –

+1

作爲一個旁註,我不會使用'memmove(token2,token2 + 1,strlen(token2));'但是會做'token2 ++'。當我修改不屬於我的記憶時,它總是讓我緊張。 – nonsensickle

+0

另外,您可以打印「errno」的內容嗎? – nonsensickle

回答

0

試開放「的test.html」而不是「\ test.html的」