tcp自链接问题

今天在Segmentfault上有人提问了一个tcp自链接问题,这里记录下。所谓tcp自链接,就是出现源ip和源端口通目的ip和目的端口彻底相同的状况,乍看起来难以想象,细细一想情理之中,本文重现下这种链接,而且说下解决思路。python

现象重现

在linux主机下运行下面的python脚本,等待一会便可出现。linux

import socket
import time

connected=False
while (not connected):
        try:
                sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
                sock.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1)
                sock.connect(('127.0.0.1',55555))
                connected=True
        except socket.error,(value,message):
                print message

        if not connected:
                print "reconnect"

print "tcp self connection occurs!"
print "try to run follow command : "
print "netstat -an|grep 55555"
time.sleep(1800)

截图以下:
netstatnginx

tcp自链接出现了!编程

缘由分析

从上面的python脚本中,能够看到它只是在不断地尝试链接55555这个端口,而且是没有socket监听这个端口,那么为什么最后却创建链接了呢?缘由在于客户端在链接服务端时,若是没有指定端口号,系统会随机分配一个。随机就意味着可能分配一个和目的端口同样的数字,此时就会出现自链接状况了。由于对于tcp协议来说,链接的流程是走的通,三次握手整个阶段都合法,链接天然能够创建。segmentfault

自链接的坏处显而易见,当程序去connect一个不处于监听的端口时,必然期待其链接失败,若是自链接出现,就意味着该端口被占用了,那么:网络

  1. 真正须要监听该端口的服务会启动失败,抛出端口已被占用的异常。socket

  2. 客户端没法正常完成数据通讯,由于这是个自链接,并非一个正常的服务。tcp

解决思路

解决办法也很简单,只要保证客户端随机的端口不会和服务监听的端口相同就能够了。那么咱们得先了解随机的范围,这个范围对应linux的/etc/sysctl.confnet.ipv4.ip_local_port_range参数,其默认值是32768 61000。也就是说随机端口会在这个范围内出现,试验中咱们选定了55555这个端口,因此出现了自链接现象。此时只要限定服务监听在32768端口如下,就不会出现自链接现象了。固然,你能够修改这个配置,只要注意保证监听端口再也不配置范围内就能够避免自链接问题了。spa

参考资料

  1. nginx 的 tcp 的连接问题
  2. 神奇的TCP Self Connect
  3. 网络编程经验:意料以外的自链接
  4. 源目的IP和端口都相同的链接出现的缘由
相关文章
相关标签/搜索