linux网络编程 多路IO转接服务器 epoll

本文深入讲解epoll的工作原理及使用方法,包括epoll_create、epoll_ctl和epoll_wait等核心函数的应用,并通过实例演示了如何利用epoll实现高效的网络服务器。
  1 /*
  2 头文件:#include<sys/epoll.h>
  3 epoll是select/poll的进阶版,同样是内核监听客户端连接服务器请求的设置
  4 
  5 原型:
  6 创建epoll句柄
  7 int epoll_create(int size);
  8 size:  设置epoll的文件描述符数量
  9 返回值:成功返回epoll句柄描述符;失败返回-1,设置errno
 10 作用:建立红黑epoll树,返回的epoll文件描述符为所建epoll红黑树的根结点(也称为句柄)
 11 eg:int epfd=epoll_create(10);
 12 */
 13 
 14 /*
 15 头文件:#include<sys/epoll.h>
 16 原型:
 17 int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);
 18 epfd:   epoll的句柄
 19 op:     控制选项
 20         EPOLL_CTL_ADD:添加节点
 21         EPOLL_CTL_MOD:修改节点
 22         EPOLL_CTL_DEL:删除节点
 23 fd:     选定需要操作的文件描述符
 24 event:结构体
 25 struct epoll_event{
 26         uin32_t         events; 
 27         epoll_data_t    data;           
 28 };      
 29 events:
 30         EPOLLIN         可读
 31         EPOLLOUT        可写
 32         EPOLLRDHUP      
 33         EPOLLPRI        
 34         EPOLLERR        异常
 35         EPOLLHUP        对应的文件描述符被挂断
 36 typedef union epoll_data{
 37         void            *ptr;
 38         int             fd;     
 39         uin32_t         u32;
 40         uint64_t        u64;
 41 }epoll_data_t;  
 42 返回值:成功返回0,失败返回-1,设置errno
 43 作用:添加或删除监听的文件描述符        
 44 eg:
 45 struct epoll_event myevent;     建立结构体
 46 myevent.events=EPOLLIN;         设置可读事件
 47 myevent.data.fd=fd;             设置文件描述符
 48 epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&myevent);      添加上面的结构体进入epoll红黑树
 49 */
 50 
 51 /*
 52 头文件:#include<sys/epoll.h>
 53 原型:
 54 int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout);
 55 events:         存储内核得到的事件的集合
 56 maxevents:      限定events的大小
 57 timeout:        监听时间 ; -1:阻塞 ; 0:立即返回,非阻塞 ; >0:指定的毫秒,阻塞
 58 返回值:成功返回有多少文件描述等待连接,时间到时返回0,出错返回-1,设置errno
 59 作用:等待监听的文件描述符满足条件
 60 eg:
 61 struct epoll_event evt[];       定义结构体数组
 62 epoll_wait(epfd,evt,sizeof(evt),(设置监听时间));
 63 */

epoll使用:

 64 void main(void)
 65 {
 66         int serv_sock,clie_sock,read_sock;
 67         serv_sock=socket(AF_INET,SOCK_STREAM,0);
 68         char buf[BUFSIZ];
 69         int n,i;
 70         struct sockaddr_in serv_sockaddr,clie_sockaddr;
 71         socklen_t clie_sockaddr_len=sizeof(clie_sockaddr);
 72         bzero(&clie_sockaddr,sizeof(clie_sockaddr));
 73         bzero(&serv_sockaddr,sizeof(serv_sockaddr));
 74         serv_sockaddr.sin_family=AF_INET;
 75         serv_sockaddr.sin_port=htons(SERV_PORT);
 76         serv_sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
 77         //设置epfd根节点,event监听事件,events收集监听数组
 78         int epfd,request;
 79         struct epoll_event event, events[10];
 80         epfd=epoll_create(10);
 81         event.events=EPOLLIN;
 82         event.data.fd=serv_sock;
 83         //添加监听事件到epfd节点
 84         epoll_ctl(epfd,EPOLL_CTL_ADD,serv_sock,&event);
 85 
 86         bind(serv_sock,(struct sockaddr *)&serv_sockaddr,sizeof(serv_sockaddr));
 87         listen(serv_sock,128);
 88 
 89         while(1){//内核监听serv_sock事件
 90                 request=epoll_wati(epfd,events,sizeof(events),-1);
 91                 if(request==-1){
 92                         perror("epoll_wait error\n");
 93                 }
 94                 for(i=0;i<request;i++) {
 95                         if(!events[i].events & EPOLLIN)//如果不是可读事件回到for继续遍历
 96                                 continue;
 97                         if(events[i].data.fd==serv_sock){
 98                                 clie_sock=acccept(serv_sock,(struct sockaddr *)&clie_sockaddr,&clie_so    ckaddr_len);
 99                                 struct epoll_event tep;
100                                 tep.events=EPOLLIN;
101                                 tep.data.fd=clie_sock;
102                                 epoll_ctl(epfd,EPOLL_CTL_ADD,clie_sock,&tep);
103                         }
104                         else {
105                                 read_sock=events.data.fd;
106                                 n=read(read_sock,buf,sizeof(buf));
107                                 if(n==0){
108                                         epoll_ctl(epfd,EPOLL_CTLDEL,read_sock,NULL);
109                                         close(read_sock);
110 
111                                 }
112                                 else{
113                                         for(i=0;i<n;i++)
114                                                 buf[i]=toupper(buf[i]);
115                                         write(read_sock,buf,n);
116                                 }
117                         }
118                 }
119         }
120 }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值