TCP的"Self-Connection"是一种比较少见的特殊现象,不少人可能从事网络相关的工做若干年也没有遇到过,甚至没有据说过,不过Google一下仍是很容易得到相关信息的。服务器
要产生一条"Self-Connection"的链接须要具有如下条件:网络
客户端和服务器运行在同一个系统中(同一台机器上),这是最基本的要求,没有这一点就无从谈起"Self-Connection";socket
服务器监听的端口号在/proc/sys/net/ipv4/ip_local_port_range所指定的范围内;
tcp
当客户端尝试链接的时候,服务器并无正常启动;spa
客户端在链接不成功的状况下会不断的重试,而且在此期间服务器一直都没有开始正常的监听流程;.net
好了,当全部上述条件都知足以后,你将会在系统中看到一条TCP链接,它的源(IP+PORT)和目的(IP+PORT)是彻底相同的两组值,而且链接状态为ESTABLISHED,以下所示:code
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"的链接就创建起来了。blog
更多关于TCP端口号选择的内容能够参见这篇文章。进程
这种状况发生时,咱们能够经过客户端的socket描述符发送数据,而后再从这个socket中将数据接收回来,从而造成一个闭环。这是由于协议栈下层是依据IP+PORT来查找socket的,因而就又找到它啦。ip
而且当"Self-Connection"发生后,不管服务器是监听在127.0.0.1仍是0.0.0.0,也不管服务器是否设置了SO_REUSEADDR,当它尝试启动时,都会得到“bind failed, errno: 98, Address already in use”的错误,这时只有将客户端进程停掉,让服务器先行启动才能恢复正常。
大好春光,你在作什么呢?:)