TCP套接字关闭

4
我一直以为如果没有实现心跳,就无法知道TCP连接的一侧是否意外死亡。如果在一侧只是杀死了进程而没有优雅地退出,则套接字无法发送FIN或让另一侧知道它已关闭。(请参见此处的一些评论http://www.perlmonks.org/?node_id=566568
但有一个股票订单服务器,我连接到它时有一个新的“断开连接时取消所有订单”功能,可以取消实时订单,即使我在本地终止进程也能正常工作,并且我的应用程序绝对没有心跳 。
那么,它是如何能够检测到我何时杀死进程的呢?我的应用程序正在运行Windows Server 2003,订单服务器运行在Suse Linux Enterprise Server 10上。Windows是否会检测与套接字关联的进程不再活动并发送FIN呢?
3个回答

9
当一个进程退出时 - 无论出于何种原因 - 操作系统将关闭它打开的TCP连接。
还有许多其他方式可以使TCP连接无法检测到:
- 有人在中间拔掉网络电缆。 - 另一端的计算机被摧毁。 - 中间的NAT网关默默地丢弃连接。 - 另一端的操作系统崩溃。 - FIN数据包丢失。
通过启用TCP keepalive,您最终会检测到它 - 至少在几个小时内。

顺便问一下,你能详细解释一下“FIN数据包丢失”的情况吗? - Pacerier
1
@Pacerier 嗯,IP 是不可靠的,有许多方式可以导致数据包丢失或损坏。如果 FIN 数据包(以及随后的 FIN 重传或 RST 数据包),它应该向对等方传达连接应该关闭的事实,但是如果这个数据包丢失了,那么对等方将永远不会知道这个事实。也许对等方正在期望接收更多的数据,但这将永远不会发生。 - nos
是的,我的意思是“数据包被丢弃或损坏的方式数量”怎么样? - Pacerier
@croraf 那个FIN数据包也可能会丢失。下一个数据包也可能会丢失。你可能认为这种情况非常罕见,永远不会发生。但它确实会发生。有人可以在客户端/服务器之间更改路由,以便数据包再也无法通过。连接可能非常拥挤,导致数据包不断丢失等等。 - nos
@nos 谢谢,我正在考虑这个问题。我想知道为什么你把它作为列表中的一个特定情况(如果由于第1、3个原因或你在之前的评论中提到的任何原因而丢失了任何其他TCP消息,那么它就是相同的情况)。我认为如果将该项目改为“中间节点拥塞”和“中间链接损坏或故障”(最后一个与项目1相同),那么会更清晰明了。 - croraf
显示剩余2条评论

2

2
据我所知,操作系统会检测进程的终止并关闭进程正在使用的所有文件描述符/套接字/句柄。因此,“杀死”应用程序和“正常终止”之间没有区别。当然,内核本身必须在运行(=电脑开机,连接线已连接...)。但是发送FIN等任务是由操作系统完成的。 此外,如果主机变得无法访问/关闭,断开连接...),中间网关(或客户端本身)可能会检测到该事件(例如,丢失载波,未更新DHCP租约...),并回复发送到已停止主机的数据包的ICMP错误(主机/网络不可达)。这会导致对等方的TCP连接断开,但仅在客户端有要发送到主机的数据包时才会发生。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接