上一小节通过阅读开源的Web服务器--tinyhttpd。大概知道了一次交互的请求信息和应答信息的具体过程。接下来我就自己简单的实现一个Web服务器。
下面这个程序只是实现一个简单的框架出来。这次先实现能够Accept客户端的请求。
简单创建web服务器
webserver.h
1 #include <iostream> 2 #include <string> 3 #include <string.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <errno.h> 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <netinet/in.h> 10 #include <arpa/inet.h> 11 #include <unistd.h> 12 #include <pthread.h> 13 #include <thread>//使用c++11的多线程 14 15 using namespace std; 16 17 class WebServer 18 { 19 public: 20 WebServer(); 21 ~WebServer(); 22 int ServerInit(u_short port); 23 int ServerError(string str); 24 int ServerAccept(); 25 int ServerClose(); 26 int ServerRequest(int cli_fd); 27 int get_line(int cli_fd,char * buf,int size);//来自tinyhttpd 28 29 int Page_200(int cli_fd); 30 int Page_501(int cli_fd); 31 private: 32 int httpd; 33 }; 34 35 int WebServer::ServerRequest(int cli_fd) 36 { 37 char buf[1024]; 38 int size=1024; 39 int i=1; 40 memset(buf,0,sizeof(buf)); 41 while((i>0)&&strcmp(" ",buf)) 42 { 43 i=get_line(cli_fd,buf,sizeof(buf)); 44 cout<<buf; 45 } 46 if(fork()==0) 47 { 48 //处理阶段 49 execl("/bin/ls","ls","/home/myuser/",NULL); 50 } 51 Page_200(cli_fd); 52 close(cli_fd); 53 return 0; 54 } 55 int WebServer::ServerAccept() 56 { 57 struct sockaddr_in cli_sin; 58 socklen_t cli_len=sizeof(cli_sin); 59 int cli_fd; 60 cli_fd=accept(httpd,(struct sockaddr *)&cli_sin,&cli_len);//阻塞等待连接 61 if(cli_fd==-1) 62 ServerError("Fail to accept"); 63 cout<<"连接进来的IP: "<<inet_ntoa(cli_sin.sin_addr)<<":"<<ntohs(cli_sin.sin_port)<<endl; 64 return cli_fd; 65 } 66 int WebServer::ServerInit(u_short port) 67 { 68 struct sockaddr_in sin; 69 int on; 70 httpd=socket(PF_INET,SOCK_STREAM,0); 71 if(httpd==-1) 72 ServerError("Fail to Socket"); 73 //init sockaddr_in 74 sin.sin_family=AF_INET; 75 sin.sin_port=htons(port); 76 sin.sin_addr.s_addr=htonl(INADDR_ANY); 77 bzero(&(sin.sin_zero),8); 78 setsockopt(httpd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); 79 if(::bind(httpd,(struct sockaddr *)&sin,sizeof(struct sockaddr))==-1) 80 ServerError("Fail to bind"); 81 //如果port指定为零那么就随机打开一个端口 82 if(port==0) 83 { 84 socklen_t len=sizeof(sin); 85 if(getsockname(httpd,(struct sockaddr *)&sin,&len)==-1) 86 ServerError("Fail to getsockname"); 87 port=ntohs(sin.sin_port); 88 } 89 if(listen(httpd,100)<0) 90 ServerError("Fail to listen"); 91 return port; 92 } 93 /////////////// 94 int WebServer::get_line(int cli_fd,char * buf,int size) 95 { 96 int i=0; 97 char c='