링크 ux 네트워크 프로 그래 밍: epoll 의 인 스 턴 스

앞에서 이미 PPC, TPC, select 등 (TPC 는 프로 세 스 처리 data, TPC 는 스 레 드 처리) 을 거 쳤 습 니 다. 앞의 두 가지 단점 은 모두 가 알 고 있 을 것 입 니 다. select (사실 poll 과 그 는 차이 가 많 지 않 습 니 다) 에 대해 단점 은 동시에 연결 할 수 있 는 fd 가 많 지 않 습 니 다. Liux 에 서 는 보통 1024 / 2048 로 큰 서버 에 부족 합 니 다!물론 우 리 는 스스로 그 값 을 수정 할 수 있다!하지만 효율 성 은 떨어진다!
       poll 을 개선 하 는 epoll 에 있어 서 프로 세 스 가 많은 socket 설명 자 를 여 는 것 을 지원 합 니 다. 즉, 이 컴퓨터 의 메모리 와 관계 가 있다 는 것 입 니 다!(일반 서버 는 다 커 요!)
       다음은 나의 작은 PC 기기 의 표시 입 니 다.
       pt@ubuntu:~$ cat /proc/sys/fs/file-max        391658        391658 개 에 이 르 렀 으 니 서버 로 서 는 분명, 헤헤 ~ ~ ~
      epoll 의 기초 지식 을 인터넷 곳곳에서 찾 을 수 있 습 니 다. 바로 epoll 가 아 닙 니 다.creat 、epoll_ctl、epoll_wait 3 함수!다 들 뒤 져 봐. 나 도 공부 하고 있어...
      이곳 은 주로 자신의 테스트 쓰레기 코드 를 붙 여 여러분 과 함께 격려 합 니 다!크 크 ~
     읊다, 읊조리다
     epoll_ctl epoll 의 이벤트 등록 함수 입 니 다. 이벤트 매개 변 수 는 다음 매크로 의 집합 일 수 있 습 니 다.     EPOLLIN:    대응 하 는 파일 설명 자 를 읽 을 수 있 음 을 표시 합 니 다 (엔 드 SOCKET 의 정상 적 인 닫 기 포함).     EPOLLOUT:   대응 하 는 파일 설명 자 를 표시 합 니 다.     EPOLLPRI:   대응 하 는 파일 설명자 에 읽 을 수 있 는 긴급 한 데이터 가 있 음 을 표시 합 니 다.     EPOLLERR:   대응 하 는 파일 설명자 에 오류 가 발생 했 음 을 표시 합 니 다.닫 힌 socket pipe broken     EPOLLHUP:   대응 하 는 파일 설명자 가 끊 겼 음 을 표시 합 니 다.예 를 들 어 RST 가방 을 받 은 경우.이 이 벤트 를 등록 할 때 이 이 벤트 는 기본적으로 추 가 됩 니 다.       EPOLLRdhup: 대응 하 는 파일 설명 자 를 나타 내 는 엔 드 socket 닫 기 이 벤트 는 주로 ET 모드 에 사 용 됩 니 다.    수평 트리거 모드 에서 엔 드 socket 이 닫 히 면 epollin 이벤트 가 계속 발생 하여 client socket 을 처리 합 니 다.    변두리 트리거 모드 에서 client 가 먼저 프로 토 콜 을 보 낸 다음 shutdown 쓰기 단 을 보 냅 니 다.epollin 이벤트 가 발생 합 니 다.그러나 처리 프로그램 이 recv 작업 을 한 번 만 할 때 recv 에서 받 은 데이터 길이 에 따라 뒤쪽 을 판독 합 니 다. 
    처리 해 야 할 프로 토 콜 이 있 는 지 여 부 는 클 라 이언 트 를 잃 어 버 리 고 이 벤트 를 닫 습 니 다.     EPOLLET: EPOLL 을 가장자리 트리거 (Edge Triggered) 모드 로 설정 합 니 다. 이것 은 수평 트리거 (Level Triggered) 에 비해 말 합 니 다.    EPOLLONESHOT: 사건 을 한 번 만 감청 합 니 다. 이번 사건 을 감청 한 후에 도 이 socket 을 계속 감청 해 야 한다 면 이 socket 을 다시 EPOLL 대기 열 에 넣 어야 합 니 다.
서버 쪽:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>			/* socket     */
#include <sys/epoll.h>			/* epoll    */
#include <fcntl.h>	                /* nonblocking   */
#include <sys/resource.h>		/*           setrlimit */

#define	MAXEPOLL	10000	/*        ,        ! */
#define	MAXLINE		1024
#define 	PORT			6000
#define	MAXBACK	1000

//!>      
//!> 
int setnonblocking( int fd )
{
	if( fcntl( fd, F_SETFL, fcntl( fd, F_GETFD, 0 )|O_NONBLOCK ) == -1 )
	{
		printf("Set blocking error : %d
", errno); return -1; } return 0; } int main( int argc, char ** argv ) { int listen_fd; int conn_fd; int epoll_fd; int nread; int cur_fds; //!> int wait_fds; //!> epoll_wait int i; struct sockaddr_in servaddr; struct sockaddr_in cliaddr; struct epoll_event ev; struct epoll_event evs[MAXEPOLL]; struct rlimit rlt; //!> char buf[MAXLINE]; socklen_t len = sizeof( struct sockaddr_in ); //!> //!> , ! //!> rlt.rlim_max = rlt.rlim_cur = MAXEPOLL; if( setrlimit( RLIMIT_NOFILE, &rlt ) == -1 ) { printf("Setrlimit Error : %d
", errno); exit( EXIT_FAILURE ); } //!> server //!> bzero( &servaddr, sizeof( servaddr ) ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl( INADDR_ANY ); servaddr.sin_port = htons( PORT ); //!> if( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) { printf("Socket Error...
" , errno ); exit( EXIT_FAILURE ); } //!> //!> if( setnonblocking( listen_fd ) == -1 ) { printf("Setnonblocking Error : %d
", errno); exit( EXIT_FAILURE ); } //!> //!> if( bind( listen_fd, ( struct sockaddr *)&servaddr, sizeof( struct sockaddr ) ) == -1 ) { printf("Bind Error : %d
", errno); exit( EXIT_FAILURE ); } //!> //!> if( listen( listen_fd, MAXBACK ) == -1 ) { printf("Listen Error : %d
", errno); exit( EXIT_FAILURE ); } //!> epoll //!> epoll_fd = epoll_create( MAXEPOLL ); //!> create ev.events = EPOLLIN | EPOLLET; //!> accept Read! ev.data.fd = listen_fd; //!> listen_fd if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev ) < 0 ) { printf("Epoll Error : %d
", errno); exit( EXIT_FAILURE ); } cur_fds = 1; while( 1 ) { if( ( wait_fds = epoll_wait( epoll_fd, evs, cur_fds, -1 ) ) == -1 ) { printf( "Epoll Wait Error : %d
", errno ); exit( EXIT_FAILURE ); } for( i = 0; i < wait_fds; i++ ) { if( evs[i].data.fd == listen_fd && cur_fds < MAXEPOLL ) //!> if { if( ( conn_fd = accept( listen_fd, (struct sockaddr *)&cliaddr, &len ) ) == -1 ) { printf("Accept Error : %d
", errno); exit( EXIT_FAILURE ); } printf( "Server get from client !
"/*, inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port */); ev.events = EPOLLIN | EPOLLET; //!> accept Read! ev.data.fd = conn_fd; //!> conn_fd if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev ) < 0 ) { printf("Epoll Error : %d
", errno); exit( EXIT_FAILURE ); } ++cur_fds; continue; } //!> //!> nread = read( evs[i].data.fd, buf, sizeof( buf ) ); if( nread <= 0 ) //!> { close( evs[i].data.fd ); epoll_ctl( epoll_fd, EPOLL_CTL_DEL, evs[i].data.fd, &ev ); //!> fd --cur_fds; //!> ! continue; } write( evs[i].data.fd, buf, nread ); //!> } } close( listen_fd ); return 0; }

client:
본인 은 게 으 르 기 때문에 지난번 select 의 client 를 사용 하 세 요. 똑 같 습 니 다. 하하:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include  <arpa/inet.h>
#include <sys/select.h>

#define MAXLINE 1024
#define SERV_PORT 6000

//!>       stdin,    server    
//!>    client     select     
void send_and_recv( int connfd )
{
	FILE * fp = stdin;
	int   lens;
	char send[MAXLINE];
	char recv[MAXLINE];
	fd_set rset;
	FD_ZERO( &rset );
	int maxfd = ( fileno( fp ) > connfd ? fileno( fp ) : connfd  + 1 );	
							        //!>          
	int n;
	
	while( 1 )
	{
		FD_SET( fileno( fp ), &rset );
		FD_SET( connfd, &rset );			//!>      rset          
								//!>                  ,
								//!>          !        !
		
		if( select( maxfd, &rset, NULL, NULL, NULL ) == -1 )
		{
			printf("Client Select Error..
"); exit(EXIT_FAILURE ); } //!> if if( FD_ISSET( connfd, &rset ) ) //!> if { printf( "client get from server ...
" ); memset( recv, 0, sizeof( recv ) ); n = read( connfd, recv, MAXLINE ); if( n == 0 ) { printf("Recv ok...
"); break; } else if( n == -1 ) { printf("Recv error...
"); break; } else { lens = strlen( recv ); recv[lens] = '\0'; //!> stdout write( STDOUT_FILENO, recv, MAXLINE ); printf("
"); } } //!> if stdin if( FD_ISSET( fileno( fp ), &rset ) ) //!> if { //!> printf("client stdin ...
"); memset( send, 0, sizeof( send ) ); if( fgets( send, MAXLINE, fp ) == NULL ) { printf("End...
"); exit( EXIT_FAILURE ); } else { //!>if( str ) lens = strlen( send ); send[lens-1] = '\0'; //!> //!> : !!!!!!!! if( strcmp( send, "q" ) == 0 ) { printf( "Bye..
" ); return; } printf("Client send : %s
", send); write( connfd, send, strlen( send ) ); } } } } int main( int argc, char ** argv ) { //!> char * SERV_IP = "10.30.97.188"; char buf[MAXLINE]; int connfd; struct sockaddr_in servaddr; if( argc != 2 ) { printf("Input server ip !
"); exit( EXIT_FAILURE ); } //!> if( ( connfd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) { printf("Socket Error...
" , errno ); exit( EXIT_FAILURE ); } //!> bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); inet_pton(AF_INET, argv[1], &servaddr.sin_addr); //!> server if( connect( connfd, ( struct sockaddr * )&servaddr, sizeof( servaddr ) ) < 0 ) { printf("Connect error..
"); exit(EXIT_FAILURE); } /*else { printf("Connet ok..
"); }*/ //!> //!> send and recv send_and_recv( connfd ); //!> close( connfd ); printf("Exit
"); return 0; }

컴 파일 실행:
gcc -o server server.c
gcc -o client client.c
./server
./client
END

좋은 웹페이지 즐겨찾기