之后会把nginx使用的简单epoll skeleton 总结一下
// epoll检测到 EPOLLIN 调用之前注册的 ngx_connection_t r结构体指针
1: ngx_epoll_module.c : rev->handler(rev);
//开始处理http请求
2: ngx_http_request.c:
ngx_http_process_request_headers(r)
ngx_http_process_request_line(r)
ngx_http_process_request(r)
//开始真正的http 处理程序
3: ngx_http_core_module.c: ngx_http_handler(r)
4: ngx_http_core_module.c: ngx_http_core_run_phases(r);
//好戏开始了,这里开始打包http头部
5: ngx_http_static_module.c: ngx_http_send_header(r)
//经过一系列的过滤模块
6:
ngx_http_chunked_filter_module.c: ngx_http_next_header_filter(r)
ngx_http_header_filter_module.c: ngx_http_write_filter(r)
//真正的发送
7:ngx_http_write_filter_module.c: chain = c->send_chain(c, r->out, limit);
ngx_linux_sendfile_chain.c: rc = writev(c->fd, header.elts, header.nelts);
相信到这里大家对nginx的http请求相应有了一个粗犷的认识 .. 他没有用EPOLLOUT 去等到缓冲变化 来send
下面是我写的一个基本功能demo epoll 的例子 和网上很多给的应该大不相同 ,因为那些好多都是漏洞百出 一压就死的
static ssize_t epoll_recv(sock_con_s *c) { static jj=0; ssize_t n_b,n_head; unsigned short len; struct iovec iov[3]; buf_head_s b_head; struct epoll_event un_use; if(c->sock_fd <= 0) return EXC_OK; int i = 0; while(1) { if(c->recv_bytes == 0 && c->if_head == 0 ){ /*recv buf head!*/ iov[0].iov_base = b_head._head; iov[0].iov_len = 2; iov[1].iov_base = &b_head._len; iov[1].iov_len = sizeof(u_short); iov[2].iov_base = b_head._context; iov[2].iov_len = 4; memset(put_buf, 0x00, sizeof(put_buf)); memset(&b_head,0x00,sizeof(b_head)); n_head = readv(c->sock_fd, iov, 3); if(n_head < 0){ if (errno == EAGAIN) return 0; else {goto PEER_OVER;} } if((n_head != sizeof(buf_head_s)) || (check_protocol(&b_head) != 0)) goto PEER_OVER; len = ntohs(b_head._len); c->total_bytes = len; c->if_head = 1; for( i = 0 ;i < 8 ;i++) printf(" %.2x",((char*)(&b_head))[i]); printf("%d\n",jj++); } n_b = recv(c->sock_fd, put_buf + c->recv_bytes, c->total_bytes - c->recv_bytes, 0); if(n_b < 0 ){ switch(errno) { case EAGAIN: return c->recv_bytes; case EINTR: break; default: goto PEER_OVER; } } else if(n_b == 0) { goto PEER_OVER;} else{ c->recv_bytes += n_b; } if(c->recv_bytes == c->total_bytes){ c->data = put_buf; mem_map(c); c->if_head = 0; c->recv_bytes = 0; } } #if 0 ev.data.fd = aEv->data.fd; ev.events = EPOLLIN ;//| EPOLLOUT; ev.events = EPOLLOUT | EPOLLET; epoll_ctl(epfd,EPOLL_CTL_MOD, aEv->data.fd ,&ev); #endif PEER_OVER: shutdown(c->sock_fd,SHUT_WR|SHUT_RD); close(c->sock_fd); mem_kick(c); epoll_ctl(ep, EPOLL_CTL_DEL, c->sock_fd, &un_use); CON_PEER(c,"",-1,NULL,-1); return EXC_OK; } static int sock_init() { struct sockaddr_in my_addr; listener = -1; if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) return EXC_ERROR; bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(SOCK_PORT); my_addr.sin_addr.s_addr = INADDR_ANY; if(sock_set(listener) == EXC_ERROR) return EXC_ERROR; if (bind (listener, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1) return EXC_ERROR; if (listen(listener, LISTEN_NUM) == -1) return EXC_ERROR; if(mon_nonblocking(listener) ==-1) return EXC_ERROR; return listener; } static int check_con(const char* sock_addr) { int i ; if(sock_addr == NULL) return EXC_ERROR; for(i = 1; i < LISTEN_NUM; i++){ if(strcmp(sock_cons[i].sock_addr,sock_addr) == 0){ //close(sock_cons[i].sock_fd); return -1; } if(strlen(sock_cons[i].sock_addr) < 1) return i; else continue; } return EXC_ERROR; } static int sock_epoll_init() { struct epoll_event ee; sock_con_s *con_accpet; int epoll_lis ; if((epoll_lis = sock_init()) == EXC_ERROR) return EXC_ERROR; memset(sock_cons,0x00,sizeof(sock_cons)); if(mem_init(0) != 0) return EXC_ERROR; con_accpet = &sock_cons[0]; CON_ACC(con_accpet, epoll_lis, accpet_init); if((ep = epoll_create(LISTEN_NUM)) == -1) return EXC_ERROR; ee.events = EPOLLIN|EPOLLET; ee.data.ptr = (void *)(uintptr_t)con_accpet; if (epoll_ctl(ep, EPOLL_CTL_ADD, epoll_lis, &ee) == -1) return EXC_ERROR; event_list = mem_alloc( sizeof(struct epoll_event) * LISTEN_NUM); if(event_list == NULL) return EXC_ERROR; return epoll_lis; } static int epoll_process() { sock_con_s *con_sock; uint32_t revents; int events; int i,c; int listen_fd ; if((listen_fd = sock_epoll_init()) <= 0){ close(ep); close(listen_fd); return EXC_ERROR; } /*indefinitely*/ while(1){ events = epoll_wait(ep, event_list, LISTEN_NUM, -1); if(errno == EINTR) continue; if(events == -1) break; /* Time out ?Impossible */ if(events == 0 ) break; for(i = 0; i < events; i++){ con_sock = event_list[i].data.ptr; revents = event_list[i].events; if( con_sock->sock_fd == listen_fd ){ con_sock->sacpt(con_sock); continue; } if ((revents & (EPOLLERR|EPOLLHUP)) && (revents & (EPOLLIN)) == 0){ revents |= EPOLLIN; } if( revents & EPOLLIN ){ if(event_list[i].data.fd < 0) continue; con_sock->srecv(con_sock); } #if 0 if( revents & EPOLLOUT ){ if(event_list[i].data.fd < 0 ) continue; } if (revents & (EPOLLERR|EPOLLHUP)) continue; #endif } } close(ep); close(listen_fd); return EXC_ERROR; } static int accpet_init(sock_con_s *c) { struct sockaddr_in peer_addr; socklen_t sock_len; struct sockaddr rem_addr; struct epoll_event ee; int accp_fd; int i; sock_con_s *peer_sock; while(1){ sock_len = sizeof(peer_addr); bzero(&peer_addr, sock_len); accp_fd = accept(listener,(struct sockaddr *)&peer_addr, &sock_len); if (accp_fd < 0) { switch(errno){ //case EINTR: case ECONNABORTED: continue; case EAGAIN: return EXC_OK; default: return EXC_ERROR; } } if(mon_nonblocking(accp_fd) == -1){ close(accp_fd); continue; } i = check_con(inet_ntoa(peer_addr.sin_addr)); if(i < 0) { shutdown(accp_fd,SHUT_WR|SHUT_RD); close(accp_fd); continue; } else{ ee.events = EPOLLIN|EPOLLET; ee.data.ptr =(void *)(uintptr_t)(&sock_cons[i]); if (epoll_ctl(ep, EPOLL_CTL_ADD, accp_fd, &ee) < 0) { shutdown(accp_fd,SHUT_WR|SHUT_RD); close(accp_fd); continue; } else{ peer_sock = (sock_con_s*)&sock_cons[i]; CON_PEER(peer_sock, inet_ntoa(peer_addr.sin_addr), accp_fd, epoll_recv, i); continue; } continue; } } }