如何突然关闭 TCP 套接字并重新连接

Posted

技术标签:

【中文标题】如何突然关闭 TCP 套接字并重新连接【英文标题】:How to Close TCP socket abruptly and reconnecting 【发布时间】:2017-02-08 20:19:11 【问题描述】:

我们在设备上使用 Linux 2.6.33。将使用通过 TCP 套接字连接到设备的 PC 应用程序。根据应用程序的请求,最多传输 1 MB 的数据。

考虑如果应用程序已连接并且工作正常,并且在设备的 IP 地址之间发生更改(这可以通过命令实现)。现在连接在应用程序上突然断开,但在设备上却没有。但用户希望重新连接到具有新 IP 地址的设备。在某些情况下,“send()”已经完成了一半,可能还没有发送所有数据。然后这种关闭不会立即发生。因此用户将无法重新连接,直到设备上的套接字关闭。

我使用“shutdown(sock, RDWR), close(sock)”序列。 netstat 输出显示:

$ netstat -nt
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0  29200 xx.xx.xx.xx:3000       xx.xx.xx.xx:50639       ESTABLISHED

因为它显示 Send-Q 仍然不是空的,所以连接仍然处于 ESTABLISED 状态。这个套接字在一段时间后关闭,我不确定它是多少时间。可能由套接字实现定义。

如何立即关闭此套接字,以便 PC 应用程序可以通过同一 TCP 端口建立新连接?

【问题讨论】:

它由完成挂起的发送或在未得到确认时中止它们所花费的时间来定义。我不明白有关“用户希望使用新 IP 地址重新连接到设备”的部分。为什么要新的 IP 地址? 因为用户命令更改了以太网 IP 地址。现在用户需要在更改 IP 后立即使用新的 IP 地址重新启动应用程序。 如何通过丢弃挂起的 Send-Q 数据包来找出关闭这个孤立套接字所需的时间? 没有“以太网 IP 地址”之类的东西。它是哪一个?以太网地址改变了? IP地址变了?两者都有? 【参考方案1】:

关闭套接字总是需要时间。但是您可以使用setsockopt() 重用相同的端口。了解更多 detail 在此链接上。

【讨论】:

【参考方案2】:

我怎样才能立即关闭这个套接字,以便新的连接结束 PC 应用程序是否可以使用相同的 TCP 端口?

你当然可以通过调用close()来关闭它,但是你真正想知道的是如何检测这种情况,以便你知道什么时候调用close()。答案是:不容易——就您的 Linux 设备而言,位于 (the_old_ip_address) 的客户端只是停止响应。 Linux 设备无法知道这种情况是由于客户端的 IP 地址已更改,而不是(例如)临时网络中断,因此 Linux 设备将在超时前继续尝试几分钟。

就解决您遇到的问题而言,最好的方法可能是设计您的服务器,使其可以同时接受和服务多个 TCP 连接。如果你这样做了,那么旧的 TCP 连接是否会持续几分钟并不重要,因为用户仍然可以立即从他的新 IP 地址重新连接并继续他的工作,而无需等待。

也就是说,另一种方法是向您的服务器添加超时,这样如果在 N 秒内没有在 TCP 套接字上发送或接收数据(对于您认为合适的任何 N 值),服务器然后显式调用在套接字上关闭()并侦听新的传入连接。但是,这不是一个很好的解决方案,因为它对 TCP 连接的性能做出了假设(即,当处于“工作”状态时,它总是每 N 秒至少发送或接收一次数据),并且这个假设可能不正确——即,如果您的客户端和服务器暂时不想发送任何内容,或者网络连接性太差以至于超过 N 秒没有数据通过。风险在于这将导致误报,导致您的服务器关闭仍然有效的 TCP 连接。因此,如果可能的话,我推荐第一种方法而不是这种方法。

【讨论】:

以上是关于如何突然关闭 TCP 套接字并重新连接的主要内容,如果未能解决你的问题,请参考以下文章

tcp socket突然关闭连接

HTML 5 - 浏览器上的 Web 套接字关闭

病毒扫描可以关闭 java TCP 套接字连接吗?

如何在 VB.NET 中检查 TCP 服务器(套接字)与 TCP 客户端的连接状态

关闭 OTP 主管拥有的 gen_tcp 侦听套接字

为啥我的 TCP 服务器套接字在一个客户端断开连接后关闭?