网络编程释疑:TCP连接拔掉网线后会发生什么

背景:前些天团队在进行终端设备和服务器端长连接业务的测试时,发现了这么一个情况:在拔掉设备端的网线后,再插上网线,有时可以继续正常的进行长接连请求,而且用的还是拔掉网线之前的那个长连接。但是有时却不能继续正常的长连接请求,需要重新建立一个新的长连接。让我尤感诧异的是第一种网线断开再插上后长连接可以恢复的情况,彻底颠覆了我一直抱有的一个所谓的“物理连接”的观念。究竟怎么回事,我们来探个究竟。


首先说说我自己发明的“物理连接”这个名词,不管怎么说我都是一个网络编程的"老手"。经常会给新人和其他有问题咨询我的同事灌输一个观念,只要网线拔掉了,说明物理连接都断了,更别提逻辑上的TCP长连接,再插上网线也只能再建立一个新的连接来继续进行请求。我做个简单的比喻:我理解的TCP长连接好比以前我们用的有线电话,甲和乙通话的过程中,倘若其中一人的电话线被拔掉了,连接就彻底断了。即使再插上电话线也不可能自动恢复通话,我们不得不重新拨通。

发现了插上网线后连接还会恢复的情况,我起初以为是简单的TCP套接字复用的情况,但是发现设备端并未编写自动重连的逻辑,这就太让我好奇和疑虑了。于是我找了一个同事配合我进行了多次测试,发现了拔掉网线后针对此TCP长连接可能会出现的 两种情况。

首先做下铺垫,做过网络编程的朋友应该都知道这么一个情况

当客户端与服务器建立起正常的TCP连接后,如果客户主机网线断开、电源掉电、或系统崩溃,服务器进程将永远不会知道(通过我们常用的select,epoll监测不到断开或错误事件),如果不主动处理或重启系统的话对于服务端来说会一直维持着这个连接,任凭服务端进程如何望穿秋水,也永远再等不到客户端的任何回应。这种情况就是半开连接,浪费了服务器端可用的文件描述符。

说明网线断开对端是不能做任何感知的,除非我们配置操作系统的SO_KEEPALIVE选项,或者进行应用层心跳检测。请参考文章《网络编程释疑之:TCP半开连接的处理》

  1. 如果网线断开的时间短暂,在SO_KEEPALIVE设定的探测时间间隔内,并且两端在此期间没有任何针对此长连接的网络操作。当连上网线后此TCP连接可以自动恢复,继续进行正常的网络操作。

  2. 如果网线断开的时间很长,超出了SO_KEEPALIVE设定的探测时间间隔,或者两端期间在此有了任何针对此长连接的网络操作。当连上网线时就会出现ETIMEDOUT或者ECONNRESET的错误。你必须重新建立一个新的长连接进行网络操作。

这件事后,我再也不敢随便发明名词了,呜呜......

posted @ 2017-12-20 22:04  鑫鑫1  阅读(1797)  评论(1编辑  收藏  举报