IO复用----epoll的使用

三组函数

(1)创建内核事件表
只是给内核一个提示,事件表需要多大;
返回值:内核事件表的文件描述符,可以理解为事件表红黑树的根;
在这里插入图片描述
(2)对内核事件表的增删改操作
注意epoll_event的结构;
在这里插入图片描述

(3)等待事件发生
第二个参数为已经就绪有事件发生的文件描述符集合**(与poll的区别就在此,poll只返回个数)**
在这里插入图片描述

poll和epoll的区别

在这里插入图片描述
代码epoll的使用

  1 #include"wrap.h"
  2 #include<errno.h>
  3 #include<sys/epoll.h>
  4 #define MAX_EVENT_NUM  1024
  5 #define BUFF_SIZE 64
  6 
  7 void delfd (int epollfd ,int fd)
  8 {
  9     struct epoll_event event;
 10     event.events = EPOLLIN;
 11     event.data.fd = fd;
 12 
 13     epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&event);
 14 }
 15 void addfd(int epollfd , int fd)//fd做成结构体才能加入事件表
 16 {
 17     struct epoll_event event;
 18     event.events = EPOLLIN;
 19     event.data.fd = fd;
 20 
 21     epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
 22 }
 23 int main(int argc , char * argv[])
 24 {
 25     if(argc  < 2 )
 26     {
 27         printf("输入IP和端口\neg:./a.out 127.0.0.2 8000\n");
 28         exit(1);
 29     }
 30     const char * ip = argv[1];
 31     int port = atoi(argv[2]);
 32     struct sockaddr_in saddr,caddr;
 33 
 34     int sfd = Socket(AF_INET,SOCK_STREAM,0);
 35 
 36     bzero(&saddr,sizeof(saddr));
 37     saddr.sin_family = AF_INET;
 38     saddr.sin_port = htons(port);
 39     inet_pton(AF_INET,ip ,&saddr.sin_addr.s_addr);
 40     Bind(sfd,(struct sockaddr*)&saddr,sizeof(saddr));
 41 
 42     Listen(sfd,5);
 43 
 44     int epollfd =  epoll_create(5);//创建epoll事件表的期望大小,返回事件表的根,即红黑树的根;
 45     if(epollfd ==-1 )
 46       perr_exit("epoll_crete error");
 47 
 48     addfd(epollfd , sfd);//封装函数,将监听socket加入epoll事件表;
 49 
 50     struct epoll_event events[MAX_EVENT_NUM];//定义就绪事件容器;
 51     while(1)
 52     {
 53         int ret = epoll_wait(epollfd,events,MAX_EVENT_NUM,-1);
 54         if(ret < 0)
 55             perr_exit("epoll-wait error");
 56         int i;
 57         for(i=0; i < ret ; ++i)
 58         {
 59             if(!events[i].events & EPOLLIN)//只关注读事件
 60               continue;
 61 
 62             if(events[i].data.fd == sfd )//监听事件sfd分一类处理,接受客户端;
 63             {
 64                 socklen_t len = sizeof(caddr);
 65                 int cfd = Accept(sfd,(struct sockaddr *)&caddr,&len);
 66                 char str[64];
 67                 printf("client cfd  ip =%s  port=%d\n",inet_ntop(AF_INET,&caddr.sin_addr.s_addr,
 68                         str,64),ntohs(caddr.sin_port));
 69                 addfd(epollfd, cfd);//客户端放入监听事件表中epoll来监听;
 70             }
 71             else//其他客户端cfd事件分一类处理,读写数据
 72             {
 73                 int sockfd = events[i].data.fd;//记录一下cfd方便使用;
 74                 char buff[BUFF_SIZE];
 75                 memset(buff,'\0',BUFF_SIZE);
 76                 int n = recv(sockfd,buff,BUFF_SIZE-1,0);
 77                 if(n == 0)//对方关闭
 78                 {
 79                     printf("client %d closing...\n",sockfd);
 80                     delfd(epollfd,sockfd);
 81                     continue;
 82                 }
 83                 if(n < 0)//接受数据出错
 84                 {
 85                     perror("client error");
 86                     delfd(epollfd,sockfd);
 87                     continue;
 88                 }
 89                 else//数据转化,并且发送数据
 90                 {
 91                     int j=0;
 92                     for(j=0;j<n;++j)
 93                       buff[j]=toupper(buff[j]);
 94                     int n =send(sockfd,buff,BUFF_SIZE-1,0);
 95                     if( n<0)
 96                       perror("send error");
 97                 }
 98 
 99             }
100 
101         }
102     }
103 
104 
105     return 0;
106 }

更多有关epoll的知识

惊群现象https://zhuanlan.zhihu.com/p/385410196
Linux 惊群效应之 Nginx 解决方案https://zhuanlan.zhihu.com/p/51251700

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YanWenCheng_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值