<Nginx> epoll

之后会把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;
		}
	}
	
}

 

猜你喜欢

转载自sunzixun.iteye.com/blog/921019
今日推荐