我们正在尝试编写一个多线程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));
}
答案 0 :(得分: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库。