请问为什么我采用epoll的EPOLLET模式同时监听fd读写的时候,会随机触发 "写" 事件?

发布于 2022-09-03 08:42:04 字数 1944 浏览 13 评论 0

1:我采用epollEPOLLET模式同时监听fd读写,客户端连接服务器之后只发送数据,按正常情况应该只会触发服务器端的EPOLLIN,但是实际情况却随机触发服务器端的EPOLLOUT
2:我目前测试如果将recv函数的recv_buf大小设置小点(我设置的为4),就不会出现这个问题。而且即使按照我下面代码的1024大小,我要是一条一条发送也不会出现问题。
3:服务端代码如下:

while(1) {
        nfds = epoll_wait(epollfd,events,1024,0);
        sleep(1);
        for(i = 0;i < nfds;i++) {
            if(events[i].data.fd == listen_fd) {           //连接请求
                conn_fd = accept(listen_fd,(struct sockaddr *)&conn_addr,&conn_len);
                printf("accept a new collection : %s\n",inet_ntoa(conn_addr.sin_addr));
                ev.data.fd = conn_fd;
                ev.events = EPOLLOUT | EPOLLIN | EPOLLET;
                epoll_ctl(epollfd,EPOLL_CTL_ADD,conn_fd,&ev);
            }
            else if(events[i].events & EPOLLIN) {        //读事件
                if((sock_fd = events[i].data.fd) < 0 ) {
                    continue;
                }
                bzero(recv_buf,1024);
                if((i = recv(sock_fd,recv_buf,1024,0) )== 0) {   //这个recv的大小会影响结果
                    close(sock_fd);
                    events[i].data.fd = -1;
                } else {
                    printf("%s\n",recv_buf);
                }
              
            }
            else if(events[i].events &  EPOLLOUT) {       //写事件
                                                  
                bzero(recv_buf,1024);
                strcpy(recv_buf,"我是服务器,收到了你的消息");
                send(events[i].data.fd,recv_buf,1024,0);
               
            }
}

4:客户端用nc 127.0.0.1 8888连接,结果会出现
5:图片描述

(备注:上面的汉字是服务器返回的,但是我客户端只是发送yang数据啊,为什么会触发服务端的写事件呢?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

电影里的梦 2022-09-10 08:42:04

因为边沿触发不是这么用的。实际上水平触发也不该这么用。建议先把水平触发弄清楚了再玩边沿触发。

监听写事件,意味着你有东西要写出去。如果你写好了,就不要再监听这个事件。只要写不会阻塞,那么文件描述符就是可写的。

send 和 recv 也不是这么用的,因为对于网络,有可能发生 short write 和 short read 的情况:数据只收发了一部分。你需要根据返回值来看是不是还有数据没发完。不要犯 Oracle 的 MySQL Connector/Python 那样的错误。

另外 nc 连上去之后是会自动读数据的。

-黛色若梦 2022-09-10 08:42:04

ev.events = EPOLLOUT | EPOLLIN | EPOLLET;
我觉得是这一行的问题,不能够在一开始拿到conn_fd 就同时注册可读事件和可写事件,而是应该在你确定已经读取完整了客户端数据之后再注册可写事件。
因为对一个conn_fd只要不阻塞它就是可写的,而你在一开始就注册了可写事件,所以当然会触发写事件。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文