今天在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)
截图以下:nginx
tcp自链接出现了!编程
从上面的python脚本中,能够看到它只是在不断地尝试链接55555这个端口,而且是没有socket监听这个端口,那么为什么最后却创建链接了呢?缘由在于客户端在链接服务端时,若是没有指定端口号,系统会随机分配一个。随机就意味着可能分配一个和目的端口同样的数字,此时就会出现自链接状况了。由于对于tcp协议来说,链接的流程是走的通,三次握手整个阶段都合法,链接天然能够创建。segmentfault
自链接的坏处显而易见,当程序去connect一个不处于监听的端口时,必然期待其链接失败,若是自链接出现,就意味着该端口被占用了,那么:网络
真正须要监听该端口的服务会启动失败,抛出端口已被占用的异常。socket
客户端没法正常完成数据通讯,由于这是个自链接,并非一个正常的服务。tcp
解决办法也很简单,只要保证客户端随机的端口不会和服务监听的端口相同就能够了。那么咱们得先了解随机的范围,这个范围对应linux的/etc/sysctl.conf
的net.ipv4.ip_local_port_range
参数,其默认值是32768 61000
。也就是说随机端口会在这个范围内出现,试验中咱们选定了55555
这个端口,因此出现了自链接现象。此时只要限定服务监听在32768
端口如下,就不会出现自链接现象了。固然,你能够修改这个配置,只要注意保证监听端口再也不配置范围内就能够避免自链接问题了。spa