在使用 FreeBSD 上运行并使用 TCP 的服务器应用程序时,我注意到即使我的应用程序明确禁用 TCP 套接字上的 SO_KEEPALIVE,也会发送 TCP 保持活动探测。
根据RFC1122 第 4.2.3.6 节(TCP 保持活动):
“如果包含保持活动,则应用程序必须能够为每个 TCP 连接打开或关闭它们,并且它们必须默认为关闭。”
我发现可调参数net.inet.tcp.always_keepalive已被启用(设置为 1),禁用它将阻止发送保活探测。
在 FreeBSD 中包含此行为的原因是什么?据我所知,Linux 和 Windows 没有这样的选项,但 FreeBSD 和 Mac OS X 有,因此它们违反了 RFC。
更具体地说,在什么情况下忽略应用程序的意愿才有意义?
对我来说这是一个简单的修复,因为我可以禁用该选项,但我想了解它为什么存在。
这个问题表明 Linux 的行为符合 RFC 的规定。
答案1
默认开启 keep-alive 的基本原理如下:https://svnweb.freebsd.org/base?view=revision&revision=47752
添加句柄来控制全局 TCP 保持活动并将其默认打开。
尽管名称如此,但它并不保持 TCP 会话处于活动状态,如果另一端消失,它会终止这些会话。这种情况经常发生在使用 NAT、动态 IP 分配或正常运行时间上限为 2^32 * 10^-3 秒的客户端上。
由于这个原因,网络流量没有明显的增加:对于实时 TCP 连接,每两小时有两个最小 TCP 数据包。
许多服务器本身已经启用了保活功能。
主机要求 RFC 已有 10 年历史,并且不了解当今 InterNet 的丢失客户情况。
无论如何,如果应用程序要求,最好关闭保持活动功能,例如(在 C 语言中):
int val = 0;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
但解决这个问题并不容易。
答案2
我认为应该有可调节的旋钮,但也许默认情况下将其关闭会更好。
我的理由是,应用程序开发人员可能会做出错误的决定,最终系统管理员应该控制这种网络策略,而不是应用程序开发人员。