TCP server 為什么一個端口可以建立多個連接?


https://segmentfault.com/q/1010000003101541

如果是tcp client用同一個本地端口去連不同的兩個服務器ip,連第二個時就會提示端口已被占用。但服務器的監聽端口,可以accept多次,建立多個socket;我的問題是服務器一個端口為什么能建立多個連接而客戶端卻不行呢?

 

5個回答

8

已采納

TCP server 可以,TCP client 也可以。一個套接字只能建立一個連接,無論對於 server 還是 client。

注意報錯消息是:

[Errno 106] (EISCONN) Transport endpoint is already connected

man 2 connect 說得很清楚了:

Generally, connection-based protocol sockets may successfully connect() only once; connectionless protocol sockets may use connect() multiple times to change their association.

就是說,TCP 套接字最多只能調用 connect 一次。那么,你的監聽套接字調用 connect 了幾次?


來點有意思的。

一個套接字不能連接兩次,並不代表一個本地地址不能用兩次,看!*加粗文字加粗文字*

>>> import socket >>> s = socket.socket() # since Linux 3.9, 見 man 7 socket >>> s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) >>> s2 = socket.socket() >>> s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) >>> s.bind(('127.0.0.1', 12345)) >>> s2.bind(('127.0.0.1', 12345)) # 都可以使用同一本地地址來連接哦 >>> s.connect(('127.0.0.1', 80)) >>> s2.connect(('127.0.0.1', 4321))
>>> netstat -npt | grep 12345 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 127.0.0.1:4321 127.0.0.1:12345 ESTABLISHED 18284/python3 tcp 0 0 127.0.0.1:12345 127.0.0.1:4321 ESTABLISHED 4568/python3 tcp 0 0 127.0.0.1:80 127.0.0.1:12345 ESTABLISHED - tcp 0 0 127.0.0.1:12345 127.0.0.1:80 ESTABLISHED 4568/python3

你們這些有女友的都弱爆了啦 :-(


更新:大家來玩 TCP: 一個人也可以建立 TCP 連接呢 - 依雲's Blog

2

內核是以一個(著名的)5元信息組來標識不同的socket的:源地址、源端口、目的地址、目的端口、協議號。任何一個不同,都不叫“同一個socket”。

0

首先,TCP鏈接是可靠的端對端的鏈接,每個TCP鏈接由4個要素組成:2組IP地址(本地和遠端),2組端口地址(本地和遠端)。其中如果需要跟端口信息綁定時,都需要調用bind函數,如果server端針對2個同樣的IP、端口組進行同樣的綁定時,第2次同樣是不成功的。

0

有個相關的問題: ftp的數據傳輸,服務器會用20端口主動連接客戶端,如果兩個客戶端同時在一下載東西,那ftp 服務器能用20端口去連接兩個ip ?(這時ftp的服務器其實是tcp里的客戶端)

能啊,看我的實驗。

— 依雲 · 2015年08月19日

展開評論
-1

不管是服務器還是客戶端,建立TCP鏈接,同一個端口都只能使用一次。

這句話其實是**錯的**!

對於TCP協議,要成功建立一個新的鏈接,需要保證新鏈接四個要素組合體的唯一性:客戶端的IP、客戶端的port、服務器端的IP、服務器端的port。也就是說,服務器端的同一個IP和port,可以和同一個客戶端的多個不同端口成功建立多個TCP鏈接(與多個不同的客戶端當然也可以),只要保證【Server IP + Server Port + Client IP + Client Port】這個組合唯一不重復即可。

> netstat -a -n -p tcp |grep 9999 tcp 0 0 127.0.0.1:51113 127.0.0.1:9999 ESTABLISHED 2701/nc tcp 0 0 127.0.0.1:51119 127.0.0.1:9999 ESTABLISHED 2752/nc 

上述結果127.0.0.1:9999中9999端口成功建立兩個TCP鏈接,也就可以理解。

**客戶端**發送TCP鏈接請求的端口,也就是后續建立TCP鏈接使用的端口,所以一旦TCP鏈接建立,端口就被占用,無法再建立第二個鏈接。

而**服務器端**有兩類端口:偵聽端口 和 后續建立TCP鏈接的端口。其中偵聽端口只負責偵聽客戶端發送來的TCP鏈接請求,不用作建立TCP鏈接使用,一旦偵聽到有客戶端發送TCP鏈接請求,就分配一個端口(一般隨機分配,且不會重復)用於建立TCP鏈接,而不是所說的服務器一個端口能建立多個連接

上述描述也比較片面,客戶端如何請求及建立鏈接,服務器端如何偵聽及是否分配新隨機端口等...應該都可以在應用層面進行控制,所以上述描述可以作為建立TCP鏈接的一種方式,僅供參考。

一些英文的參考:
How do multiple clients connect simultaneously to one port, say 80, on a server?
TCP : two different sockets sharing a port?

如果真是這樣,為什么netstat 命令只看到監聽端口而沒有你說的另一個隨機端口?

— hyanleo · 2015年08月16日

accept 才不會分配新端口號,不然大家不用考慮單機的 C10K 問題了,反正端口號不夠用不是?

— 依雲 · 2015年08月19日

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM