【问题标题】:SO_KEEPALIVE behavior is enabled by default on Linux?在 Linux 上默认启用 SO_KEEPALIVE 行为?
【发布时间】:2014-02-11 14:28:06
【问题描述】:

我有一个使用 TCP 套接字用 C 语言编写的客户端/服务器应用程序。我想知道使用在客户端套接字上启用的 SO_KEEPALIVE 选项的死服务器进程。我正在使用 Linux。

我将默认时间从 2 小时修改为 10 分钟。

echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time

我使用 setsockopt() 在客户端套接字上启用了 SO_KEEPALIVE。我在向客户端发送数据时故意杀死(kill -9)服务器进程。

正如预期的那样,在 10 分钟超时(加上额外的探测时间)后,客户端套接字得到通知(读取(scoket,...)返回零)。

然而,令我惊讶的是,即使我在客户端套接字上禁用此选项,它仍然会在指定的超时后收到通知(read() 返回零)。

在 Linux 中是否默认启用此行为?

另外,我觉得 read() 返回零是不合适的,当对等体死亡时 read() 不应该返回一些错误吗?

【问题讨论】:

  • 当你杀死一个 Linux 进程(或者进程崩溃)时,所有的套接字都会被彻底关闭,并且与对等方的连接会被重置。如果你想测试真正死掉的客户端,你将不得不对来自服务器的所有流量进行防火墙或拔掉电缆或使内核崩溃。
  • 你可以通过getsockopt检查...

标签: linux sockets tcp linux-kernel network-programming


【解决方案1】:

Keepalive 导致连接重置。导致read() 返回零的唯一原因是接收到一个 FIN。因此,您收到了 FIN,而不是 keepalive 终止,因此这并不表明在 Linux 中默认启用 keepalive。这将违反 RFC 1122。

【讨论】:

  • 感谢您的信息。假设默认情况下或我的更改未启用 keepalive。但是我杀死了服务器进程。一段时间后客户端如何收到 FIN?
  • 没关系。我杀死了服务器进程,但它有一个 sleep() 调用,它似乎是作为另一个进程产生的......并且仍在与客户端通信。谢谢。
  • 但是还有其他事情......如果我突然终止服务器进程(和相关的子进程), read() 也会返回零。基本上,当客户端套接字准备好读取时,客户端等待 select() 调用得到通知....当我终止服务器时,它立即得到通知并且 read() 返回零。为什么这样?我突然杀掉了服务端,服务端没有调用close()或shutdown(),那么是谁把FIN包发给客户端的?
  • and...keepalive 也会导致连接超时
  • @ernesto read() 返回零表示客户端收到了一个 FIN,这意味着发送者发送了一个 FIN,这意味着即使你突然杀死了你的服务器,操作系统仍然代表它发送一个 FIN .
猜你喜欢
  • 2011-06-22
  • 1970-01-01
  • 2021-07-18
  • 2014-10-28
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多