linux - 使用epoll检测网线拔出错误

标签 linux network-programming epoll

我测试过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/

相关文章:

python - 如何使用 rpm 规范文件中的参数调用函数?

iOS:Unix:Mac 从静态库中提取有关受支持架构的信息。如何?

linux - subprocess.Popen : does not retun complete output , 当通过 crontab 运行时

linux - 是否可以模仿 UDP 数据包的源/目标 IP?

EPOLLHUP 是否可以触发由 EPOLLONESHOT 禁用的描述符事件?

node.js - libuv 是在 unix 中使用 epoll 还是 select(2)

linux - 为什么必须在边缘触发的 epoll 函数中使用非阻塞 fd?

linux - 测量Linux中的执行时间

c - 获取网关以用于 ANSI C 中的给定 ip

java - UDP 数据包内容在传输时发生变化