1

我们正在尝试编写一个多线程的 Web 服务器,但我们不知道如何从每个 HTTP 请求(网页)中获取文件名到一个简单的服务器。我们还关心每个文件的大小。任何想法?

这是 server.c 文件的主要内容:

     int main(int argc, char *argv[])
     {
        int listenfd, connfd, port, clientlen;
        struct sockaddr_in clientaddr;

        getargs(&port, argc, argv);

        listenfd = Open_listenfd(port);
        thread_pool_init();    

        for(;;){
                pthread_mutex_lock(&pool_lock);
                while(buf_count == request_limit)
                        pthread_cond_wait(&signal_worker, &pool_lock);
                clientlen = sizeof(clientaddr);
                connfd = Accept(listenfd, (SA *)&clientaddr, (socklen_t *) &clientlen);

        //get/parse html file name here 
        //get file size using stat

                put(connfd);

                pthread_cond_signal(&signal_worker);
                pthread_mutex_unlock(&pool_lock);
        }

我们在 client.c 中的 open_connection 代码将 HTTP 请求发送到 server.c 文件,如下所示:

void * open_connection( ){

        clientfd = Open_clientfd(host, port);

        clientSend(clientfd, filename);

        pthread_mutex_lock(&lock);
        clientPrint(clientfd);
        pthread_mutex_unlock(&lock);

        Close(clientfd);
        sem_post(&cond);
        return NULL;
}



 //Send an HTTP request for the specified file 

void clientSend(int fd, char *filename)
{
  char buf[MAXLINE];
  char hostname[MAXLINE];

  Gethostname(hostname, MAXLINE);

  //Form and send the HTTP request 
  sprintf(buf, "GET %s HTTP/1.1\n", filename);
  sprintf(buf, "%shost: %s\n\r\n", buf, hostname);
  Rio_writen(fd, buf, strlen(buf));
}
4

1 回答 1

0

收到 HTTP 请求后,您需要对其进行解析以检索所请求文件的名称,然后将文件发送回客户端。

我发布了一个简单的代码,可用于处理我在一个实验中使用过的 HTTP 请求。它真的很简单,它没有考虑到 HTTP 协议的很多不同特性,基本上它只适用于 GET 请求,但它可能是一个很好的起点。

recv_request是一个从用于与客户端通信的套接字读取请求的函数。

#define PORT                 80  
#define WEBROOT              "/var/www/localhost/htdocs/"

void handle_connection(int sockfd, struct sockaddr_in *client_addr_ptr) {
   unsigned char *ptr, request[REQUEST], resource[REQUEST];
   int fd, length;

   memset(request, 0,  REQUEST); 
   memset(resource, 0,  REQUEST); 
   length = recv_request(sockfd, request);

   printf("Got request from %s:%d lenght: %d  \n", inet_ntoa(client_addr_ptr->sin_addr), ntohs(client_addr_ptr->sin_port),length);
   puts("--------------------------------\n"); 
   printf("%.*s", 500, request);
   puts("--------------------------------"); 


   ptr = strstr(request, " HTTP/"); // search for valid looking request
   if(ptr == NULL) { // then this isn't valid HTTP
      printf(" NOT HTTP!\n");
   } else {
      *ptr = 0; // terminate the buffer at the end of the URL
      ptr = NULL; // set ptr to NULL (used to flag for an invalid request)
      if(strncmp(request, "GET ", 4) == 0)  // get request
         ptr = request+4; // ptr is the URL
      if(strncmp(request, "HEAD ", 5) == 0) // head request
         ptr = request+5; // ptr is the URL

      if(ptr == NULL) { // then this is not a recognized request
         printf("\tUNKNOWN REQUEST!\n");
      } else { // valid request, with ptr pointing to the resource name
         if (ptr[strlen(ptr) - 1] == '/')  // for resources ending with '/'
            strcat(ptr, "index.html");     // add 'index.html' to the end
         strcpy(resource, WEBROOT);     // begin resource with web root path
         strcat(resource, ptr);         //  and join it with resource path
         fd = open(resource, O_RDONLY, 0); // try to open the file
         printf("Opening \'%s\'\t", resource);
         if(fd == -1) { // if file is not found
            printf(" 404 Not Found\n");
            send_string(sockfd, "HTTP/1.0 404 NOT FOUND\r\n");
            send_string(sockfd, "Server: Tiny webserver\r\n\r\n");
            send_string(sockfd, "<html><head><title>404 Not Found</title></head>");
            send_string(sockfd, "<body><h1>URL not found</h1></body></html>\r\n");
         } else {      // otherwise, serve up the file
            printf(" 200 OK\n\n");
            send_string(sockfd, "HTTP/1.0 200 OK\r\n");
            send_string(sockfd, "Server: Tiny webserver\r\n\r\n");
            if(ptr == request + 4) { // then this is a GET request
               if( (length = get_file_size(fd)) == -1)
                  fatal("getting resource file size");
               if( (ptr = (unsigned char *) malloc(length)) == NULL)
                  fatal("allocating memory for reading resource");
               read(fd, ptr, length); // read the file into memory
               write(sockfd, ptr, length);  // send it to socket
               free(ptr); // free file memory
            }
            close(fd); // close the file
         } // end if block for file found/not found
      } // end if block for valid request
   } // end if block for valid HTTP
   shutdown(sockfd, SHUT_RDWR); // close the socket gracefully

   return; 
}

你应该看看curl库。

于 2013-11-11T00:09:20.720 回答