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和端口都相同的鏈接出現的緣由
相關文章
相關標籤/搜索