【问题标题】:Active closure of server sockets服务器套接字的主动关闭
【发布时间】:2013-01-22 04:07:57
【问题描述】:

我有一个小型服务器(TCP 服务器),它在端口 5000 上最多接受 10 个连接。我在侦听模式下创建了一个套接字并接受连接。当接受成功时,我创建一个新线程并处理该线程中的流量。我在同一台机器上有一个客户端,它能够与该服务器连接和通信。

现在要了解 TIME_WAIT,我使用 ctrl+c 终止我的服务器应用程序。我希望看到处于“已建立”状态的服务器套接字被转移到“TIME_WAIT”。但是,当我在关闭后执行 netstat 时,我没有看到处于“TIME_WAIT”状态的单个套接字。我知道“侦听”模式下的套接字直接转换为 CLOSED 状态。但我很困惑为什么接受返回且当前处于已建立状态的套接字不处于 TIME_WAIT 状态。

(我在linux机器上,tcp_fin_timeout值设置为1min。)

我的 tcpdump 如下所示:

localhost.49388 > localhost.5000:
    Flags [S], cksum 0xfe30 (incorrect -> 0xaa93), seq 3264533269, win 32792,
    options [mss 16396,sackOK,TS val 20216234 ecr 0,nop,wscale 3], length 0              
localhost.5000 > localhost.49388:
    Flags [S.], cksum 0xfe30 (incorrect -> 0xc6a0), seq 3352338762, ack 3264533270, win 32768,
    options [mss 16396,sackOK,TS val 20216234 ecr 20216234,nop,wscale 3], length 0
localhost.49388 > localhost.5000:
    Flags [.], cksum 0xfe28 (incorrect -> 0x9fbe), ack 1, win 4099,
    options [nop,nop,TS val 20216234 ecr 20216234], length 0           
localhost.5000 > localhost.49388:
    Flags [P.], cksum 0xfe42 (incorrect -> 0xa300), seq 1:27, ack 1, win 4096,
    options [nop,nop,TS val 20216484 ecr 20216234], length 26           
localhost.49388 > localhost.5000:
    Flags [.], cksum 0xfe28 (incorrect -> 0x9db0), ack 27, win 4099,
    options [nop,nop,TS val 20216484 ecr 20216484], length 0          
localhost.49388 > localhost.5000:
    Flags [P.], cksum 0x0211 (incorrect -> 0x6be1), seq 1:1001, ack 27, win 4099,
    options [nop,nop,TS val 20216484 ecr 20216484], length 1000              
localhost.5000 > localhost.49388:
    Flags [.], cksum 0xfe28 (incorrect -> 0x91cb), ack 1001, win 6144,
    options [nop,nop,TS val 20216484 ecr 20216484], length 0     
localhost.5000 > localhost.49388:
    Flags [R.], cksum 0xfe28 (incorrect -> 0x8eeb), seq 27, ack 1001, win 6144,
    options [nop,nop,TS val 20217216 ecr 20216484], length 0

【问题讨论】:

  • 您在其他机器上的客户端上试过吗?
  • 不会检查。为什么会不一样?
  • 我在两台机器之间试了试,同样的步骤。现在我可以在 TIME_WAIT 中看到服务器套接字。为什么会有这种差异?
  • 除非您运行的是一些被破解的内核,否则应该没有任何区别。你如何运行netstat

标签: linux sockets networking tcp


【解决方案1】:

*但是我很困惑为什么接受返回并且当前处于已建立状态的套接字不处于 TIME_WAIT 状态。*

因为你杀死了进程,阻止了任何有序的关闭。只有当进程在套接字上实际调用close()(或shutdown())时,您才会看到TIME_WAIT——这将向对等方发送FIN——然后保持活动足够长的时间以接收ACK发送给对等方的FIN 和对等方自己的FIN(为此将发回ACK)。有三种方法可以到达TIME_WAIT,其中一种必须发生才能建立TIME_WAIT,但只有当进程仍然存在以转换到 FIN_WAIT1 时才会发生这种情况,这是所有三个路径的开始。您的 Ctrl-C 甚至阻止了启动序列的 close()

要查看TIME_WAIT,您必须安排您的进程主动关闭套接字,例如在为SIGHUP 安装的处理程序中,或通过某种输入机制。随时终止进程是确保看不到您想要的内容的好方法。

【讨论】:

  • 这根本不是真的。 TCP 连接断开发生在内核中,而不是在用户空间中。
  • 当然。如果你杀死一个进程——而不是让它以有序的方式退出——从另一端发送的任何东西都会得到一个 RST。
  • 拉出tcpdump 并跟踪连接,^C 连接的一侧。你会看到一个FIN 发送出去。内核网络堆栈会为您做这些(除其他外)。
  • @Nikoli:是的,是的。这就是为什么我期待看到 TIME_WAIT。我认为任何主动关闭都应该在 TIME_WAIT 结束。如果服务器应用程序关闭,那么内核会发送 FIN,这间接意味着服务器套接字会主动关闭并且应该以 TIME_WAIT 结束。我的理解正确吗?
  • 不管内核是否发送一个礼貌的 FIN 作为进程拆除的一部分,套接字将不会转换到 FIN_WAIT1。甚至来自该 FIN 另一侧的 ACK 也会产生 RST!转换到 FIN_WAIT1 需要应用程序级别的 close()/shutdown() 作为触发事件。如果信号处理程序捕获 SIGINT 并调用 exit(),那也足够了。但不会通过未捕获的信号终止进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
  • 2014-06-26
  • 1970-01-01
  • 2013-02-17
  • 2020-09-17
  • 2017-03-06
相关资源
最近更新 更多