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

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

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数据啊,为什么会触发服务端的写事件呢?)


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

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

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

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

【热门文章】
【热门文章】