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
- epoll编程
- epoll编程实例
- linux服务器编程--EPOLL
- linux 网络编程 epoll
- 网络编程: epoll
- epoll服务器编程-demo
- 网络编程 epoll
- Linux Epoll编程
- linux下epoll编程
- socket编程之epoll
- Linux--编程--epoll
- Linux_C 编程:epoll详解
- epoll网络编程实例
- 网络编程 select epoll
- 【网络编程】epoll简介
- epoll网络编程实例
- epoll编程框架
- linux编程--多路复用---epoll
- decode 实例
- Linux线程池
- Java 设计模式 接口型模式 之 适配器Adapter模式 (二)
- 全程软件测试之测试需求分析与计划(3)
- OpenGL: WIN7的64BIT下OPENGL着色语言(GLSL)开发环境配置
- epoll编程
- kerberos认证协议浅析
- Linux调试工具strace和gdb常用命令小结
- 黑马程序员_面向对象
- eclipse基断点调试
- 标题: Microsoft SQL Server Management Studio ------------------------------ 附加数据库时出错。有关详细信息,请单击“消息”列中
- 编程回忆之Android回忆(Android权限大全)
- 在 UNIX 和 Linux 系统上安装和配置 WebSphere Application Server
- Nginx 403 forbidden的解决办法