我测试过epoll
在网线拔掉的情况下:
- 服务器开启3000端口
- 创建epoll并将
server_fd
加入epoll - 接受客户端(客户端使用
telnet
)并将client_fd
加入epoll - 向客户端发送数据
- 拔掉网线后,
epoll_wait
永远不会得到任何与client_fd
相关的事件
我想检测这种情况下的错误。有没有额外的解决方案?应用程序是否需要实现心跳方法进行 self 检测?
最佳答案
这里有两个选择:
- 实现应用层心跳。换句话说,您编写代码来检测空闲连接并定期发送应用层消息以实质上探测连接并确保它仍然打开
- 你使用 TCP keepalive。这基本上将实现和处理心跳消息的工作转移到 TCP 层。这对你来说似乎是个不错的选择。
要启用和配置 TCP keepalive,您需要使用 setsockopts(2)
更改 client_fd
套接字选项。您需要检查/更改 3 个参数:
TCP_KEEPCNT
- 这是在任何给定时间允许的未完成、未答复的探测数。如果在给定时间间隔内发送超过TCP_KEEPCNT
次探测而没有回复,则认为连接已断开。TCP_KEEPIDLE
- 在开始发送探测数据包之前连接需要空闲的时间量。TCP_KEEPINTVL
- 各个探测之间的时间。
所以,你在 client_fd
上做这样的事情:
int tcp_keepcnt = 3;
int tcp_keepidle = 30;
int tcp_keepintvl = 60;
setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt));
setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle));
setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl));
断开的连接被 epoll(7)
报告为可读,带有 EPOLLHUP
标志。请注意,订单关闭将被报告为可读没有 EPOLLHUP
,但 read(2)
将返回 0。
请记住,检测到死连接并不是立竿见影的。这需要一段时间。例如,使用上述参数,大约需要 3 分钟。
关于linux - 使用epoll检测网线拔出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31307369/