免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2791 | 回复: 5
打印 上一主题 下一主题

[Linux] Linux下epoll的一些问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-06-28 09:08 |只看该作者 |倒序浏览
小弟使用EPOLLIN来触发可读事件,按照网上说的,ET模式下,只有缓冲区从不可读变成可读才会触发EPOLLIN时间,可现在写了一个测试程序,客户端每次发多个字节,服务器每次只收一个字节,但每次都会触发EPOLLIN事件,如果只收一个字节,缓冲区还有数据,下次发送就应该不会再触发EPOLLIN事件(ET模式下),服务端代码如下:
  1. #include <iostream>
  2. #include <cstring>
  3. #include <sys/epoll.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <arpa/inet.h>
  7. #include <netinet/in.h>
  8. #include <errno.h>
  9. #include <fcntl.h>

  10. int main(void)
  11. {
  12.     int serfd = socket(AF_INET, SOCK_STREAM, 0);
  13.     int clifd;
  14.     int ret;
  15.     if(serfd < 0)
  16.         std::cout << "Create serfd fail!\n";

  17.     struct sockaddr_in cliaddr, seraddr;
  18.     bzero(&seraddr, sizeof(seraddr));
  19.     seraddr.sin_family = AF_INET;
  20.     seraddr.sin_port = htons(12439);
  21.     seraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
  22.     int on = 1;
  23.     setsockopt(serfd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
  24.     bind(serfd, (struct sockaddr*)&seraddr, sizeof(seraddr));
  25.     listen(serfd, 20);

  26.     socklen_t len = sizeof(cliaddr);
  27.     bzero(&cliaddr, sizeof(seraddr));
  28.     clifd = accept(serfd, (struct sockaddr*)&cliaddr, &len);
  29.     if(clifd < -1){
  30.         std::cout << strerror(errno) << std::endl;
  31.         close(serfd);
  32.         return 0;
  33.     }

  34.     fcntl(clifd, F_SETFL, O_NONBLOCK);

  35.     //Create epoll
  36.     int epfd = epoll_create(1024);
  37.     struct epoll_event ev;
  38.     struct epoll_event events[1024];
  39.     ev.events = EPOLLET | EPOLLIN ;
  40.     ev.data.fd = clifd;
  41.     epoll_ctl(epfd, EPOLL_CTL_ADD, clifd, &ev);

  42.     while(1)
  43.     {
  44.         int num = epoll_wait(epfd, events, 1024, -1);
  45.         char buf[1024] = {0};
  46.         for(int i = 0; i < num; i++)
  47.         {
  48.             if(events[i].events & EPOLLIN){
  49.                 std::cout << "Ready to read!\n";
  50.                 std::cout << "size=" << read(events[i].data.fd, buf, 1)
  51.                           << "\tbuf=[" << buf << ']' << std::endl;
  52.             }
  53.             if(events[i].events & EPOLLOUT){
  54.                 std::cout << "Ready to write!\n";
  55.             }
  56.         }

  57.     }
  58.     return 0;
  59. }

复制代码
客户端使用: nc 来连接,并发送数据,第一次发了abcd,触发了EPOLLIN,但服务器只收一个字节,第二次发了ef,依然触发了EPOLLIN。

服务器端的接收情况:

此外:如果我注册的时候是EPOLLET|EPOLLOUT ,为什么这个EPOLLOUT每次都会触发?
谢谢各位!

论坛徽章:
16
CU十二周年纪念徽章
日期:2013-10-24 15:41:3415-16赛季CBA联赛之广东
日期:2015-12-23 21:21:55青铜圣斗士
日期:2015-12-05 10:35:30黄金圣斗士
日期:2015-11-26 20:42:16神斗士
日期:2015-11-19 12:47:50每日论坛发贴之星
日期:2015-11-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-18 06:20:002015亚冠之城南
日期:2015-11-10 19:10:492015亚冠之萨济拖拉机
日期:2015-10-28 18:47:282015亚冠之柏太阳神
日期:2015-08-30 17:21:492015亚冠之山东鲁能
日期:2015-07-07 18:48:39摩羯座
日期:2014-08-29 23:01:42
2 [报告]
发表于 2015-06-28 11:30 |只看该作者
hi,
按照EPOLLET 代码实现,应该是如果你没有读取完毕
并且底层驱动也没有数据发送过来的哈。
这时候你的epoll_wait 是不能等待相关的事件啦。
例如,你在读取一个字节后,你客服端不发送消息过来,那么你在epoll_wait
对应的文件符 是一直没有相应的事件报告的(在EPOLLET模式下)
如果你不使用EPOLLET模式,那么你在读取一个字节后,再次epoll_wait,
即使你的客服端不发送消息,也会有读事件报告的(因为你还有数据没读完)

论坛徽章:
0
3 [报告]
发表于 2015-06-28 12:29 |只看该作者
回复 2# tc1989tc
嗯,是的,比如我客户端传了5个字节,epoll服务器第一次触发EPOLLIN的时候,我只收了1个字节,
这样的话,不是还有4个字节留在内核缓冲区中吗(网上说要触发EPOLLIN,一直要读到返回EAGAIN错误)?
下次客户端再发数据,由于是EPOLLET的,但此时内核缓冲区不为空(还有4个字节),没有从不可读变成可读,那它应该不会再次触发EPOLLIN啊!
可我现在做的测试结果,刚好相反!
   

论坛徽章:
16
CU十二周年纪念徽章
日期:2013-10-24 15:41:3415-16赛季CBA联赛之广东
日期:2015-12-23 21:21:55青铜圣斗士
日期:2015-12-05 10:35:30黄金圣斗士
日期:2015-11-26 20:42:16神斗士
日期:2015-11-19 12:47:50每日论坛发贴之星
日期:2015-11-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-18 06:20:002015亚冠之城南
日期:2015-11-10 19:10:492015亚冠之萨济拖拉机
日期:2015-10-28 18:47:282015亚冠之柏太阳神
日期:2015-08-30 17:21:492015亚冠之山东鲁能
日期:2015-07-07 18:48:39摩羯座
日期:2014-08-29 23:01:42
4 [报告]
发表于 2015-06-28 15:26 |只看该作者
看linux的evenepoll.c 里面的实现  
和你测试的结果是一致的。
它只保证啦一次报文的边缘触发
也就是驱动有报文来  有等待队列 他还是会**的

论坛徽章:
0
5 [报告]
发表于 2015-06-28 15:44 |只看该作者
回复 4# tc1989tc
嗯勒,谢谢你!


   
KingaChou 该用户已被删除
6 [报告]
发表于 2015-09-02 09:09 来自手机 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP