想在Linux下实现一个简单的web Server并不难。一个最简单的HTTP Server不过是一个高级的文件服务器,不断地接收客户端(浏览器)发送的HTTP请求,解析请求,处理请求,然后像客户端回送数据。在大多是情况下,(GET、POST命令),服务求回传给客户端的都是文件(HTML 文档, 图片,JavaScript脚本等等)。

下面是一个极简单的HTTP Server的demo,虽然只处理GET请求并发送单一文件,但基本展示了web server的框架。我的例子试图将功能和结构做到最精简,这样,一个http server的基本结构,便一目了然。

[cpp] view plain copy
 
  1. #include<sys/socket.h>  
  2. #include<errno.h>  
  3. #include<netinet/in.h>  
  4. #include<string.h>  
  5. #include<stdio.h>  
  6.   
  7. #define BUF_LEN 1028  
  8. #define SERVER_PORT 8080  
  9.   
  10. //定义好的html页面,实际情况下web server基本是从本地文件系统读取html文件   
  11. const static char http_error_hdr[] = "HTTP/1.1 404 Not Found\r\nContent-type: text/html\r\n\r\n";  
  12. const static char http_html_hdr[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";  
  13. const static char http_index_html[] =   
  14. "<html><head><title>Congrats!</title></head>"  
  15. "<body><h1>Welcome to our HTTP server demo!</h1>"  
  16. "<p>This is a just small test page.</body></html>";  
  17.   
  18. //解析到HTTP请求的文件后,发送本地文件系统中的文件  
  19. //这里,我们处理对index文件的请求,发送我们预定好的html文件  
  20. //呵呵,一切从简!   
  21. int http_send_file(char *filename, int sockfd)  
  22. {  
  23.     if(!strcmp(filename, "/")){  
  24.         //通过write函数发送http响应报文;报文包括HTTP响应头和响应内容--HTML文件   
  25.         write(sockfd, http_html_hdr, strlen(http_html_hdr));  
  26.         write(sockfd, http_index_html, strlen(http_index_html));  
  27.     }  
  28.     else{  
  29.          // 文件未找到情况下发送404error响应   
  30.         printf("%s:file not find!\n",filename);  
  31.         write(sockfd, http_error_hdr, strlen(http_error_hdr));  
  32.     }  
  33.   return 0;  
  34. }  
  35.   
  36. //HTTP请求解析   
  37. void serve(int sockfd){  
  38.     char buf[BUF_LEN];  
  39.     read(sockfd, buf, BUF_LEN);  
  40.     if(!strncmp(buf, "GET", 3)){  
  41.         char *file = buf + 4;  
  42.         char *space = strchr(file, ' ');  
  43.         *space = '\0';  
  44.         http_send_file(file, sockfd);  
  45.     }  
  46.     else{  
  47.          //其他HTTP请求处理,如POST,HEAD等 。这里我们只处理GET   
  48.         printf("unsupported request!\n");  
  49.         return;  
  50.     }  
  51. }  
  52.   
  53. void main(){  
  54.     int sockfd,err,newfd;  
  55.     struct sockaddr_in addr;  
  56.     //建立TCP套接字   
  57.     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  58.     if(sockfd < 0){  
  59.         perror("socket creation failed!\n");  
  60.         return;  
  61.     }  
  62.     memset(&addr, 0, sizeof(addr));  
  63.     addr.sin_family = AF_INET;  
  64.     //这里要注意,端口号一定要使用htons先转化为网络字节序,否则绑定的实际端口  
  65.     //可能和你需要的不同   
  66.     addr.sin_port = htons(SERVER_PORT);  
  67.     addr.sin_addr.s_addr = INADDR_ANY;  
  68.     if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))){  
  69.         perror("socket binding failed!\n");  
  70.         return;  
  71.     }  
  72.     listen(sockfd, 128);  
  73.     for(;;){  
  74.         //不间断接收HTTP请求并处理,这里使用单线程,在实际情况下考虑到效率一般多线程   
  75.         newfd = accept(sockfd, NULL, NULL);  
  76.         serve(newfd);  
  77.         close(newfd);  
  78.     }  
  79. }  
posted on 2017-06-01 14:05  baraka  阅读(2352)  评论(0编辑  收藏  举报