#TCP你学得会# 之 "Self-Connection"知多少

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

    TCP的"Self-Connection"是一种比较少见的特殊现象,很多人可能从事网络相关的工作若干年也没有遇到过,甚至没有听说过,不过Google一下还是很容易获得相关信息的。

    要产生一条"Self-Connection"的连接需要具备以下条件:

  • 客户端和服务器运行在同一个系统中(同一台机器上),这是最基本的要求,没有这一点就无从谈起"Self-Connection";

  • 服务器监听的端口号在/proc/sys/net/ipv4/ip_local_port_range所指定的范围内;

  • 当客户端尝试连接的时候,服务器并没有正常启动;

  • 客户端在连接不成功的情况下会不断的重试,并且在此期间服务器一直都没有开始正常的监听流程;

    好了,当所有上述条件都满足之后,你将会在系统中看到一条TCP连接,它的源(IP+PORT)和目的(IP+PORT)是完全相同的两组值,并且连接状态为ESTABLISHED,如下所示:

tcp        0      0 127.0.0.1:36666         127.0.0.1:36666         ESTABLISHED 1489/a.out

   产生这种情况的原因就是客户端在连接服务器的时候,内核会从/proc/sys/net/ipv4/ip_local_port_range所指定的端口范围内选择一个合适的值作为它的源端口号,由于这时服务器并不存在,因此连接失败,下一次重连时内核又会选择一个新的源端口号,而由于此时服务器仍然没有正常启动,因此他原本要监听的端口号处于空闲状态,就有机会被选为客户端的源端口号,当这种情况发生时,协议栈会将它作为"TCP同时打开"这种特殊情况来处理,而没有做特殊干预,于是,一条"Self-Connection"的连接就建立起来了。

    更多关于TCP端口号选择的内容可以参见这篇文章。

    这种情况发生时,我们可以通过客户端的socket描述符发送数据,然后再从这个socket中将数据接收回来,从而形成一个闭环。这是因为协议栈下层是依据IP+PORT来查找socket的,于是就又找到它啦。

    并且当"Self-Connection"发生后,无论服务器是监听在127.0.0.1还是0.0.0.0,也无论服务器是否设置了SO_REUSEADDR,当它尝试启动时,都会获得“bind failed, errno: 98, Address already in use”的错误,这时只有将客户端进程停掉,让服务器先行启动才能恢复正常。


    大好春光,你在做什么呢?:)




转载于:https://my.oschina.net/u/2310891/blog/656219

你可能感兴趣的:(#TCP你学得会# 之 "Self-Connection"知多少)