![TCP 连接仅在 Linux 上可见](https://linux22.com/image/748302/TCP%20%E8%BF%9E%E6%8E%A5%E4%BB%85%E5%9C%A8%20Linux%20%E4%B8%8A%E5%8F%AF%E8%A7%81.png)
我正在处理两台机器之间的通信问题。机器 A 是 Windows Server 2012 机器,机器 B 是 Centos 8 机器。机器 A 是在 VMWare 下运行的虚拟机,而机器 B 是物理 x86_64 机器。我不相信两台机器之间有任何防火墙。
我们在 A 和 B 上安装了通过 TCP 相互通信的应用程序。机器 B 打开一个侦听 TCP 端口并接受传入连接,而机器 A 则连接到该 TCP 端口。这通常可以正常工作。
但是,有一种情况会导致故障。如果我们终止 A 上的应用程序并重新启动它,它确实会与 B 建立新连接。但是,A 和 B 之间的通信会在此端口上停止一段时间。
我发现,在 A 上,执行终止/重新启动后,anetstat
仅显示新连接的 TCP 连接ESTABLISHED
(根本不显示旧连接),而在 B 上,anetstat
将旧连接和新连接都显示为ESTABLISHED
。深入研究在 B 上运行的应用程序后,我确定,由于它仍将旧连接视为活动状态(因为操作系统将其报告为 ESTABLISHED),因此它在接收新连接上的请求时会继续在旧连接上发送响应。
过了一段时间(约 2 小时?),机器 B 似乎检测到旧的 TCP 连接已断开,并开始向正确的 TCP 连接发送响应,因此通信又开始工作了。
让我感到困惑的是为什么输出netstat
不对称。如果 B 看到连接为ESTABLISHED
,但 A 根本看不到连接,那么我的结论是 A 或 B 未遵循 TCP 标准。我的直觉是,当应用程序被终止时,机器 A 上的 Windows 没有干净地关闭 TCP 连接,导致连接断开而不是正常关闭。
如果我的结论是正确的,并且有一台机器没有正确执行 TCP,那么我会看到一些潜在的解决方案,但没有一个完全符合我的需求:
- 当检测到新连接时,关闭 B 上的旧连接:这是我当前的解决方案
- 使用应用程序级超时(或 TCP keepalive?)来检测连接何时断开:这是我首选的解决方案
- 当应用程序被终止时,彻底关闭 A 上的连接:这很好,但我无法控制 A 上的应用程序,因此很难进行此更改
或者,是否有某种方法可以调整 Windows 中的设置,使断开的连接能够干净地关闭,或者在 CentOS 中进行配置,使 Linux 更快地检测到断开的连接?