epoll编程

来源:互联网 发布:软件开发管理规范 编辑:程序博客网 时间:2024/05/22 03:39

前言

本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下:

客户端从标准输入读入一行,发送到服务端

服务端从网络读取一行,然后输出到客户端

客户端收到服务端的响应,输出这一行到标准输出

 

服务端

代码如下:

复制代码
  1 #include<unistd.h>  2 #include<sys/types.h>       /* basic system data types */  3 #include<sys/socket.h>      /* basic socket definitions */  4 #include<netinet/in.h>      /* sockaddr_in{} and other Internet defns */  5 #include<arpa/inet.h>       /* inet(3) functions */  6 #include<sys/epoll.h> /* epoll function */  7 #include<fcntl.h>     /* nonblocking */  8 #include<sys/resource.h> /*setrlimit */  9  10 #include<stdlib.h> 11 #include<errno.h> 12 #include<stdio.h> 13 #include<string.h> 14  15  16  17 #define MAXEPOLLSIZE 10000 18 #define MAXLINE 10240 19 int handle( int connfd ); 20 int setnonblocking( int sockfd ) 21 { 22     if ( fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFD, 0 ) | O_NONBLOCK ) == -1 ) 23     { 24         return -1; 25     } 26     return 0; 27 } 28  29 int main( int argc, char **argv ) 30 { 31     int  servPort = 6888; 32     int listenq = 1024; 33  34     int listenfd, connfd, kdpfd, nfds, n, nread, curfds, acceptCount = 0; 35     struct sockaddr_in servaddr, cliaddr; 36     socklen_t socklen = sizeof( struct sockaddr_in ); 37     struct epoll_event ev; 38     struct epoll_event events[MAXEPOLLSIZE]; 39     struct rlimit rt; 40     char buf[MAXLINE]; 41  42     /* 设置每个进程允许打开的最大文件数 */ 43     rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE; 44     if ( setrlimit( RLIMIT_NOFILE, &rt ) == -1 ) 45     { 46         perror( "setrlimit error" ); 47         return -1; 48     } 49  50     bzero( &servaddr, sizeof( servaddr ) ); 51     servaddr.sin_family = AF_INET; 52     servaddr.sin_addr.s_addr = htonl ( INADDR_ANY ); 53     servaddr.sin_port = htons ( servPort ); 54  55     listenfd = socket( AF_INET, SOCK_STREAM, 0 ); 56     if ( listenfd == -1 ) 57     { 58         perror( "can't create socket file" ); 59         return -1; 60     } 61  62     int opt = 1; 63     setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof( opt ) ); 64  65     if ( setnonblocking( listenfd ) < 0 ) 66     { 67         perror( "setnonblock error" ); 68     } 69  70     if ( bind( listenfd, ( struct sockaddr * ) &servaddr, sizeof( struct sockaddr ) ) == -1 ) 71     { 72         perror( "bind error" ); 73         return -1; 74     } 75  76     if ( listen( listenfd, listenq ) == -1 ) 77     { 78         perror( "listen error" ); 79         return -1; 80     } 81  82     /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */ 83     kdpfd = epoll_create( MAXEPOLLSIZE ); 84     ev.events = EPOLLIN | EPOLLET; 85     ev.data.fd = listenfd; 86     if ( epoll_ctl( kdpfd, EPOLL_CTL_ADD, listenfd, &ev ) < 0 ) 87     { 88         fprintf( stderr, "epoll set insertion error: fd=%d\n", listenfd ); 89         return -1; 90     } 91     curfds = 1; 92  93     printf( "epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq ); 94  95     for ( ;; ) 96     { 97         /* 等待有事件发生 */ 98         nfds = epoll_wait( kdpfd, events, curfds, -1 ); 99         if ( nfds == -1 )100         {101             perror( "epoll_wait" );102             continue;103         }104 105         /* 处理所有事件 */106         for ( n = 0; n < nfds; ++n )107         {108             if ( events[n].data.fd == listenfd )109             {110                 connfd = accept( listenfd, ( struct sockaddr * )&cliaddr, &socklen );111                 if ( connfd < 0 )112                 {113                     perror( "accept error" );114                     continue;115                 }116 117                 sprintf( buf, "accept form %s:%d\n", inet_ntoa( cliaddr.sin_addr ), cliaddr.sin_port );118                 printf( "%d:%s", ++acceptCount, buf );119 120                 if ( curfds >= MAXEPOLLSIZE )121                 {122                     fprintf( stderr, "too many connection, more than %d\n", MAXEPOLLSIZE );123                     close( connfd );124                     continue;125                 }126                 if ( setnonblocking( connfd ) < 0 )127                 {128                     perror( "setnonblocking error" );129                 }130                 ev.events = EPOLLIN | EPOLLET;131                 ev.data.fd = connfd;132                 if ( epoll_ctl( kdpfd, EPOLL_CTL_ADD, connfd, &ev ) < 0 )133                 {134                     fprintf( stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror( errno ) );135                     return -1;136                 }137                 curfds++;138                 continue;139             }140 141             // 处理客户端请求142             if ( handle( events[n].data.fd ) < 0 )143             {144                 epoll_ctl( kdpfd, EPOLL_CTL_DEL, events[n].data.fd, &ev );145                 curfds--;146             }147         }148     }149     close( listenfd );150     return 0;151 }152 int handle( int connfd )153 {154     int nread;155     char buf[MAXLINE];156     nread = read( connfd, buf, MAXLINE );157 158     if ( nread == 0 )159     {160         printf( "client close the connection\n" );161         close( connfd );162         return -1;163     }164 165     if ( nread < 0 )166     {167         perror( "read error" );168         close( connfd );169         return -1;170     }171 172     write( connfd, buf, nread );173     return 0;174 }
0 0