簡體   English   中英

系統中的兩個不同的 UDP 套接字可以綁定同一個端口嗎?

[英]Can two different UDP socket in a system bind same port?

我有一個使用 UDP 連接的應用程序,現在當我嘗試多次運行該應用程序時,它向我拋出異常

java.net.BindException: Address already in use: Cannot bind

但是在我的另一個使用 tcp 連接的應用程序中,我可以打開同一個應用程序的兩個實例並且它工作正常。 為什么此錯誤僅與 UDP 連接有關?

編輯:

TCP socket:

Socket clientSocket= new Socket(ipAddress, 8000);
Socket clientSocket1= new Socket(ipAddress, 8000);

如果我像上面那樣創建 TCP 套接字,使用相同的端口,它不會拋出任何錯誤。 但是如果我用 UDP Socket 來做這件事,它會拋出一個異常,為什么?

它與 TCP 和 UDP 之間的區別有關。 當您創建 TCP 套接字時,您正在創建到另一台機器上的端口的同步客戶端連接,並且當您連接到一個地址時,您實際上也在套接字上獲得了一個本地端口。 因此,在您的示例代碼中,創建的兩個套接字可能是

clientSocket = localhost:2649 <-> ipAddress:8000
clientSocket1 = localhost:2650 <-> ipAddress:8000

請注意,雖然它們的遠程地址相同,但本地地址具有不同的端口,這就是允許的原因。 所以在這里本地和遠程機器可以使用已建立的端口可靠地來回發送數據。

對於 UDP,情況並非如此(我假設您使用的是 DatagramSocket)。 由於 UDP 是異步的(而不是像 TCP 那樣的同步),為了接收數據,您不會創建到另一台特定機器的綁定,例如,如果您要嘗試

DatagramSocket udp1 = new DatagramSocket(8000); // = localhost:8000 <-> ?
DatagramSocket udp2 = new DatagramSocket(8000); // = localhost:8000 <-> ?

udp 套接字不知道數據來自哪里,因此不能像 TCP那樣有唯一的映射,而且與 TCP 不同的是,您指定的端口是您機器的端口,而不是遠程機器端口

當您創建 UDP 套接字時,另一種思考方式就像創建一個 TCP 服務器套接字。 當您創建 TCP 服務器套接字時,它正在等待來自某台機器的連接,但該機器未知,當您創建 TCP 服務器套接字時,您指定的端口是本地端口:

ServerSocket ss1 = new ServerSocket(8000); // = localhost:8000 <-> ?
ServerSocket ss2 = new ServerSocket(8000); // = localhost:8000 <-> ?

再次像 UDP 一樣,這將創建綁定異常,因為端口用於本地機器並且映射不再唯一。 但是,當您接受服務器套接字上的連接時,遠程機器會發揮作用以使套接字唯一,就像您創建到遠程機器的 Socket 一樣:

Socket s1 = ss1.accept();// localhost:8000 <-> remoteIp1:12345
Socket s2 = ss1.accept();// localhost:8000 <-> remoteIp2:54321

請注意,雖然本地地址相同,但套接字的遠程地址不同,因此總映射 (localip:port<->remoteip:port) 現在是唯一的。

因此,在某種程度上,您可以將 UDP 套接字視為有點像 TCP 服務器套接字,這就是您必須將其綁定到唯一端口的原因。

您確定 TCP 應用程序確實使用非零端口號進行綁定嗎? 它也不應該適用於 TCP。 端口號的目的是確定將流量路由到哪個正在運行的應用程序實例; 如果兩個應用程序分別將兩個套接字綁定到同一個端口號,那么路由就變得不可能,這就是錯誤的原因。

您必須將套接字設置為可共享的,或稱為 SO_REUSEPORT。

在 C 或 C++ 中,這是通過 setsockopt 函數完成的。 當你綁定到一個端口,然后設置SO_REUSEPORT,另一個進程也可以綁定一個socket到同一個端口號。 一個例子是多進程應用程序,使用多個 CPU 內核盡可能快地讀取傳入的數據。 完成此操作后,流量在進程之間進行負載平衡,或者更有可能的是,第一個讀取數據的人獲取它(使用 UDP)。

對於 TCP,這僅與進入的新連接相關。當新連接進入時,第一個接受()連接的進程擁有該連接,但端口號仍由綁定到它的所有進程共享,並且新的隨后將連接移交給第一個使用 accept() 獲取它的人。 從 TCP 套接字共享 READING 是沒有意義的(盡管多線程應用程序可以這樣做),因為數據是作為沒​​有記錄分隔符的流傳入的,所以讓多個讀者讀取它只是,好,一個類比,多人閱讀同一本書並在閱讀時撕掉書頁。 你會留下每個讀者都有一個語無倫次的混亂。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM