tcp自連接問題

今天在Segmentfault上有人提問了一個tcp自連接問題,這裏記錄下。所謂tcp自連接,就是出現源ip和源端口通目的ip和目的端口完全相同的情況,乍看起來不可思議,細細一想情理之中,本文重現下這種連接,並且說下解決思路。

現象重現

在linux主機下運行下面的python腳本,等待一會即可出現。

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)

截圖如下:

tcp自連接出現了!


原因分析

從上面的python腳本中,可以看到它只是在不斷地嘗試連接55555這個端口,並且是沒有socket監聽這個端口,那麼爲何最後卻建立連接了呢?原因在於客戶端在連接服務端時,如果沒有指定端口號,系統會隨機分配一個。隨機就意味着可能分配一個和目的端口一樣的數字,此時就會出現自連接情況了。因爲對於tcp協議來講,連接的流程是走的通,三次握手整個階段都合法,連接自然可以建立。

自連接的壞處顯而易見,當程序去connect一個不處於監聽的端口時,必然期待其連接失敗,如果自連接出現,就意味着該端口被佔用了,那麼:

  1. 真正需要監聽該端口的服務會啓動失敗,拋出端口已被佔用的異常。

  2. 客戶端無法正常完成數據通信,因爲這是個自連接,並不是一個正常的服務。

解決思路

解決辦法也很簡單,只要保證客戶端隨機的端口不會和服務監聽的端口相同就可以了。那麼我們得先了解隨機的範圍,這個範圍對應linux的/etc/sysctl.confnet.ipv4.ip_local_port_range參數,其默認值是32768 61000。也就是說隨機端口會在這個範圍內出現,試驗中我們選定了55555這個端口,所以出現了自連接現象。此時只要限定服務監聽在32768端口以下,就不會出現自連接現象了。當然,你可以修改這個配置,只要注意保證監聽端口不再配置範圍內就可以避免自連接問題了。





原文地址:https://segmentfault.com/a/1190000002396411

發佈了72 篇原創文章 · 獲贊 54 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章