Epoll basic interface with the process of establishing a TCP connection view:
Network uses Epoll to implement a TCP server-a novice bird-51CTO Tech Blog
http://shaungqiran.blog.51cto.com/10532904/1784410
Focus:
< Span style= "font-family: ' Microsoft Jas Black ', ' Microsoft Yahei '; Font-size:20px;color:rgb (255,0,0);" > epoll followed by multiplexed I/O model . . So we have to choose the right time to read or write. For the kernel, to a socket file descriptor The listener of the read and write events is a separate (readable, not necessarily writable). Therefore, to achieve the highest efficiency. The user-made I/O operation should also read, write separate.
In the case of read-write separation, the server-side service is sometimes required for client-submitted information for HTTP servers. Read and write separations can cause an inability to respond effectively. So we have to maintain a buffer for ourselves, to spring up the valid contents of each socket FD. Until the write event is used, and then the memory is reclaimed.
Each event handle has a not-long-used pointer (void*). Just so we can use it to point to our buffers,
typedef Union EPOLL_DATA {
void *ptr; Our available ptr is used to store a pointer to the buffer
int FD;
__uint32_t u32;
__uint64_t U64;
} epoll_data_t;
Events of interest and events that are triggered
struct Epoll_event {
__uint32_t events; /* Epoll Events */
epoll_data_t data; /* USER Data variable */
};
Epoll.c
#include "httpd.h" #include <sys/epoll.h> #include <malloc.h> #include < netdb.h> #include <sys/utsname.h> #include <net/if.h> #include <sys/ioctl.h># define _maxfd_ 10 #define errorip -1int set_non_block (INT&NBSP;FD) {Int old_ Flag=fcntl (FD,F_GETFL); if (old_flag<0) {perror ("fcntl");//exit ( -4); return -1;} if (Fcntl (fd,f_setfl,old_flag| O_nonblock) <0) {perror ("fcntl"); return -1;} return 0;} Int startup (Char* ip,int port) {int sock=socket (af_inet,sock_stream,0); struct sockaddr _IN&NBSP;SERVER;SERVER.SIN_FAMILY=AF_INET;SERVER.SIN_ADDR.S_ADDR=INET_ADDR (IP); server.sin_port=htons (port); int flag=0;//printf ("port %d %d", Port, (htons (port))), if (Bind (sock, struct sockaddr *) &server,sizeof (server)) <0) {perror ("bind"); exit (-2);} if ( setsockopt (sock, sol_socket, so_reuseaddr, &flag, sizeof (flag)) == -1) { perror ("setsockopt"); exit (1); } if (Listen (sock,50 ) {<0) {perror ("listen"); exit (-3);} Return sock;} Void usage (Char* arg) {printf ("usage %s [ip] [port]\n", Arg);} Void epollup (int sock) {int epoll_fd=epoll_create); if (epoll_fd<0) {perror ("Epoll"); return;} int timeout_num=0;int done=0;int timeout=10000;int i=0;int ret_num=-1;struct epoll_event ev;struct epoll_event event[100];ev.data.fd=sock;ev.events=epollin| epollet;//fd_num=1;//printf ("listen sock%d\n", sock); if (Epoll_ctl (Epoll_fd,epoll_ctl_add,sock,&ev) < 0) {perror ("Epoll_ctl"); return ;} while (!done) {switch (ret_num=epoll_wait (epoll_fd,event,256,timeout)) {case -1:{perror ("epoll_wait"); Case 0 :{if (timeout_num++>20) done=1;printf ("time out...\n"); break;} Default:{for (i=0;i<ret_num;++i) {if (Event[i].data.fd==sock&&event[i].events&epollin) {int new_sock=-1;struct sockaddr_in client;socklen_t len=sizeof (client); while (New_sock=accept (sock, (struct sockaddr*) &client,&len)) {if (new_sock<0) {//perror ("accept"); if (Set_non_block (new_sock) <0) {echo_error (new_sock,500); continue;} printf (" epoll :%d\n", new_sock); ev.data.fd=new_sock;ev.events=epollin| Epollet;if (Epoll_ctl (Epoll_fd,epoll_ctl_add,new_sock,&ev) <0) {perror ("Epoll_ctl"); Echo_error (New_sock, 503); continue;}} break;} Else {if (Event[i].events&epollin) {int fd=event[i].data.fd;pev_buf pev= (pev_buf) malloc ( sizeof (EV_BUF)); Event[i].data.ptr=pev;pev->fd=fd;if (Epoll_recv_http (&event[i]) <0) {free (PEV); if (epoll _ctl (Epoll_fd,epoll_ctl_del,fd,&ev) <0) perror ("Read epoll_ctl_del"); Close (FD); continue;} Elseevent[i].events=epollout;} if (event[i].events&epollout) {int fd= ((pev_buf) (EveNT[I].DATA.PTR)->fd;epoll_echo_http (event+i), if (Epoll_ctl (Epoll_fd,epoll_ctl_del,fd,&ev) <0) perror (" Out_ctl_del ") Free ((PEV_BUF) event[i].data.ptr);p rintf (" epoll close :%d\n ", FD); close (FD);}} Break;}}}} Int main (int argc,char* argv[]) {if (argc!=3) {usage (argv[0]); exit (-1);} Int port=atoi (argv[2]); Int listen_sock;char* ip=null;if (strcmp (argv[1], "any") ==0) {INT&NBSP;SFD, intr;struct ifreq buf[16]; struct ifconf ifc; sfd = socket (af_inet, sock_dgram, 0); if (sfd < 0) return errorip;ifc.ifc_len = sizeof (BUF);ifc.ifc_buf = ( caddr_t) buf;if (IOCTL (sfd, siocgifconf, (char *) &ifc)) return errorip;intr = ifc.ifc_len / sizeof (struct ifreq);while (intr-- > 0 && ioctl (sfd, siocgifaddr, (CHAR&Nbsp;*) &buf[intr]); close (SFD); Ip= inet_ntoa (((struct sockaddr_in*) (&BUF[INTR].IFR_ADDR))- >&NBSP;SIN_ADDR);p rintf ("%s\n", IP); listen_sock=startup (Ip,port);} Else listen_sock=startup ( argv[1],port);//printf ("port %s %d", Argv[2],port); set_non_block (Listen_sock); Epollup (Listen_sock); close (listen_sock); return 0;}
httpd.h
#ifndef __MYHTTP__#define __MYHTTP__#include <stdio.h> #include <netinet/in.h># include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <errno.h > #include <fcntl.h> #include <sys/stat.h> #include <sys/epoll.h> #include <sys/sendfile.h> #define &NBSP;_SIZE_&NBSP;1024TYPEDEF&NBSP;STRUCT&NBSP;EVENT_BUF{//Self-maintained structure int fd;char method[10];//http Request method char url[1024];//Request parameter Char parameter[1024];//get method parameter int cgi;//need to use cgi method}ev_buf,*pev_buf;//rename Char* get_text (INT&NBSP;FD,CHAR*&NBSP;BUF);//Get Message body int epoll_recv_http (Struct epoll_event *ev);//Accept Message Int epoll_echo_http (struct epoll_event * ev);//Send Xiaoxivoid cgi_action (int fd,char* method,char* url,char* parameter);//cgi interface int get_Line (int sock_fd,char * buf);//read a row of information from socket fd void* http_action (void* Client_sock);//void echo_error (Int fd,int _errno);//Echo error message Void error_all (int fd,int err,char* reason);//All error messages void echo_html (int fd,const char* url,int size );//Echo Request webpage #endif
HTTPD.C
#include "httpd.h" #define DEFAULT "/default.html" #define IMG "src_html" #define cgi "src_cgi" Int times=0;void echo_error (int fd,int _errno) {printf ("join err\n") ; switch (_errno) {case 400://bad request //client request has a syntax error and cannot be understood by the server break;case 404://// The requested resource does not exist, eg: the wrong url//printf ("*******404\n") was entered, Error_all (fd,404, "not_find!!"); break;case 401://request Unauthorized, this status code must be used with the Www-authenticate header domain break;case 403://server received the request, but refused to provide service Unexpected error occurred on break;case 500:// internal server error //server break;case 503:// The server unavailable //server is currently unable to process client requests and may return to normal break;default:break after a period of time;}} Void error_all (Int fd,int err,char* reason) {char buf[_size_]= ""; Char error[_SIZE _]= ""; sprintf (buf, "http/1.0 %d %s\r\n\r\n", Err,reason); sprintf (Error, " %d %s", Err,reason); printf ("err buf:%s\n error:%s", Buf,error); write (Fd,buf,strlen (BUF)); WRITe (fd, "
Network HTTP Server-v2-epoll version