epoll_wait同时触发数据接收与连接关闭时recv()的返回值问题
epoll同时触发数据到达与连接关闭事件时recv()的返回结果
当客户端发送数据后调用close(),服务器延迟调用epoll_wait()导致一次调用中同时触发EPOLLIN(数据到达)和EPOLLRDHUP/EPOLLHUP(连接关闭)事件时,recv()的表现分为两步:
- 第一次调用
recv():会正常读取客户端发送的所有数据,返回实际读取到的字节数,和普通有数据可读的场景完全一致。 - 数据读取完毕后再次调用
recv():此时接收缓冲区已空,内核会返回0,提示连接已关闭。
原因说明
TCP是字节流协议,客户端调用close()的流程是先将发送缓冲区的所有数据发送至服务器,再发送FIN包触发连接关闭事件。此时服务器的TCP连接处于半关闭状态:接收缓冲区仍有未读取的数据,同时对方已发起关闭请求。epoll会同时上报这两个事件,但内核处理recv()时会优先返回已缓存的数据,直到缓冲区清空后才会返回连接关闭的标识(0)。
另外需要注意:如果调用recv()时使用MSG_PEEK标志,只会查看缓冲区数据而不清除,后续正常调用recv()依然会先读取数据,再返回0。
内容的提问来源于stack exchange,提问作者Jacks Fengggg
相关产品推荐
相关产品推荐

