Linux 何时/如何决定在应用程序终止时关闭套接字?

hud*_*dac 8 linux networking tcp

我有一个服务器进程和一个客户端进程运行在同一台 Linux 机器上。

有时,当我kill -9是客户端时,我会看到发送tcpdump了一条FIN, ACK消息。当然,死去的客户不可能做到这一点,因为他已经残酷地与SIGKILL. 所以我猜 Linux 操作系统会处理连接关闭。

有时我看不到任何连接关闭处理并且连接保持“已建立”(由netstat)。

我总是看到一个连接被关闭Linux ubuntu 4.4.0-53-generic
有时我看到一个连接被关闭Linux 3.13.11(纯内核,而不是 Ubuntu)。

我的问题是:

  1. Linux 是否处理关闭连接?
    1.1 在SIGKILL
    1.2. 当应用程序正常关闭,但没有调用close()?
  2. 此功能在内核版本3.13.114.4.0? Ubuntu 有什么用吗?
  3. 如果这两个进程不在同一台 Linux 机器上怎么办:它的行为会一样吗?
  4. 为什么连接有时会保持“已建立”?
  5. 我知道 TCPkeepalive套接字选项。如果 Linux 真的处理关闭连接。它们为什么存在?仅当FIN,?ACK数据包丢失时?

111*_*--- 8

一个广泛的问题。也许有人可以对您有关特定内核版本之间的内核 TCP 堆栈的问题进行权衡。

几个普遍的答案:

从客户端

  1. 如果有SIGKILL信号,内核会终止程序执行,并关闭进程的打开文件描述符。内核对 TCP 套接字的处理与常规文件略有不同,因为它们需要刷新并通过 TCP 关闭过程。

    来自客户端的立即“FIN,ACK”和更长的套接字关闭之间的差异可能取决于客户端应用程序终止时客户端 TCP 连接所处的状态。但通常内核会关闭应用程序的打开套接字。

从服务器端

  1. 服务器并不总是知道客户端何时断开连接。确定客户端是否挂断的最可靠方法是尝试从返回 EOF 的套接字读取。

    TCP 旨在对连接延迟和间歇性故障具有弹性。这也意味着在FIN, ACK4 路断开握手没有发生的情况下可靠地检测断开连接的一些挑战。

概括

您可能kill -9在客户端上看到的是服务器进入CLOSE_WAITTCP 状态,等待 TCP 超时。这可能需要一段时间。即使客户端消失了,如果内核没有处理 TCP 断开握手,服务器将不得不超时。

如果我记得这可能需要几秒钟的时间,这可能是为什么您仍然看到ESTABLISHED由于在同一主机上运行客户端和服务器。