基于epoll实现的一个简单web服务器
本文使用epoll建立一个简单的web服务器。通过epoll实现对过个端口的管理,非阻塞的数据发送。
使用到数据结构
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <sys/types.h>#include <unistd.h>#include <errno.h>#include <sys/epoll.h> /*设这文件句柄sfd为非阻塞**/static int make_socket_non_blocking (int sfd){ int flags, s; flags = fcntl (sfd, F_GETFL, 0); if (flags == -1) { perror ("fcntl"); return -1; } flags |= O_NONBLOCK; s = fcntl (sfd, F_SETFL, flags); if (s == -1) { perror ("fcntl"); return -1; } return 0;} /*创建epoll管理最大文件句柄的个数*parameter* @maxfds:最大的句柄个数。也就是网站数目。端口的数目*/int epoll_init(int maxfds){ return epoll_create(maxfds);} /*设这epoll管理每个文件句柄的参数和方法*parameter* @fd:要管理socket文件句柄* @maxfds:管理socket文件句柄的个数*/static struct epoll_event * epoll_event_init(int * fd, int maxfds){ struct epoll_event *events; int i = 0; if(0 >= maxfds || NULL ==fd) return NULL; events = (struct epoll_event *)malloc( sizeof(struct epoll_event) * maxfds); for(; i < maxfds; i++) { events[i].data.fd = fd[i]; events[i].events = EPOLLIN | EPOLLET; } return events;} int epoll_handler(int epfd, int * fd, int maxfds){ struct epoll_event *events = epoll_event_init(fd, maxfds); struct epoll_event *ev = events; int i = 0; for(; i < maxfds; i++) { epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], ev); ev++; } } /* @description:开始服务端监听@parameterip:web服务器的地址port:web服务器的端口@result:成功返回创建socket套接字标识,错误返回-1 */int socket_listen( char *ip, unsigned short int port){ int res_socket; //返回值 int res, on; struct sockaddr_in address; struct in_addr in_ip; res = res_socket = socket(AF_INET, SOCK_STREAM, 0); setsockopt(res_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); memset(&address, 0, sizeof(address)); address.sin_family = AF_INET ; address.sin_port =htons(port); address.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("127.0.0.1"); res = bind( res_socket, (struct sockaddr *) &address, sizeof( address ) ); if(res) { printf( "port is used , not to repeat bind\n" ); exit(101); }; res = listen(res_socket,5); if(res) { printf( "listen port is error ;\n" ); exit( 102 ); }; return res_socket ;} void send_http1(int conn_socket){ char *send_buf = "HTTP/1.1 200 OK\r\nServer: Reage webserver\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><title>epoll learn</title></head><body><h1>Reage Test111111</h1>Hello World! </body></html>\r\n\r\n"; write(conn_socket, send_buf, strlen(send_buf));}void send_http2(int conn_socket){ char *send_buf = "HTTP/1.1 200 OK\r\nServer: Reage webserver\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><title>epoll learn</title></head><body><h1>Reage Test22222</h1>Hello World! </body></html>\r\n\r\n"; write(conn_socket, send_buf, strlen(send_buf));} int main(int argc, char * argv[] ){ int res_socket[2]; struct epoll_event event[100]; struct sockaddr_in client_addr; int len; res_socket[0] = socket_listen( "127.0.0.1", 1025) ; res_socket[1] = socket_listen( "127.0.0.1", 1024) ; make_socket_non_blocking(res_socket[0]); make_socket_non_blocking(res_socket[1]); int epfd = epoll_init(2); epoll_handler(epfd, res_socket, 2); while(1) { int count = epoll_wait(epfd, event, 2, -1); while(count--) { sleep(10); int connfd = accept(event[count].data.fd, (struct sockaddr *)&client_addr, &len); //针对不同的端口,即是不同的网站进行不同的处理 if( event[count].data.fd == res_socket[0]) send_http1(connfd); else send_http2(connfd); close(connfd); } } }
blogs:http://blog.csdn.net/rentiansheng/article/details/8684194