簡體   English   中英

Java ServerSocket如何在接受客戶端后獲得綁定到同一本地端口的新套接字?

[英]How does Java ServerSocket get a new socket bound to the same local port after accept the client?

我對Socket和ServerSocket端口的使用感到困惑。 Oracle關於套接字的java教程說明如下:

什么是插座?

通常,服務器在特定計算機上運行,​​並且具有綁定到特定端口號的套接字。 服務器只是等待,監聽套接字以便客戶端發出連接請求。 在客戶端:客戶端知道運行服務器的計算機的主機名以及服務器正在偵聽的端口號。 要發出連接請求,客戶端會嘗試與服務器的計算機和端口上的服務器會合。 客戶端還需要向服務器標識自己,以便綁定到在此連接期間將使用的本地端口號。 這通常由系統分配。

如果一切順利,服務器將接受連接。 接受后,服務器獲取綁定到同一本地端口的新套接字,並將其遠程端點設置為客戶端的地址和端口。 它需要一個新的套接字,以便它可以繼續監聽原始套接字的連接請求,同時滿足連接客戶端的需求。

在客戶端,如果接受連接,則成功創建套接字,客戶端可以使用套接字與服務器通信。 客戶端和服務器現在可以通過寫入或讀取其套接字進行通信。

我嘗試了以下代碼進行測試。 但它引發了一個例外。

try {
    ServerSocket serverSocket = new ServerSocket(8080);

    Socket socket = serverSocket.accept();

    // This prints 8080
    System.out.println("Local port of accepted socket : " + socket.getLocalPort());  

    // But this throws java.net.BindException: Address already in use: JVM_Bind 
    Socket myClientSocket = new Socket("www.google.com", 80, null, 8080);

} catch (Exception e) {
    e.printStackTrace();
}

我的問題很明顯。 serverSocket.accept()返回的套接字可以使用相同的本地端口( 8080 ),為什么我創建的套接字不能使用它?

為了簡單起見,偵聽TCP套接字已經明確綁定到端口,因此您無法將第二個TCP套接字顯式綁定到同一端口(除非兩個套接字也明確綁定到不同的IP地址,不包括INADDR_ANY)。

接受的套接字不會通過明確的“綁定”過程。 它們自動獲取本地IP地址和端口,如果您在沒有綁定的情況下連接它,則出站套接字也是如此。

您的服務器和客戶端使用相同的本地端口進行通信。 當您創建服務器套接字時,您“說”它必須在8080端口上偵聽。 沒關系。 任何想要與服務器套接字通信的人都必須使用此類端口。

但是,就在下面你正在創建一個客戶端套接字,使用端口80連接谷歌網站(谷歌正在監聽該端口),在最后一個參數中,你說這個套接字必須使用本地端口8080來建立連接。 一次只有一個連接可以使用一個端口,這就是為什么你得到java.net.BindException,服務器和客戶端連接都使用8080。

我的建議...從套接字客戶端構造函數中獲取最后兩個參數,或者更改本地客戶端端口(總是得到一個高數字以避免與其他進程相同的問題):

Socket myClientSocket = new Socket("www.google.com", 80);

要么

Socket myClientSocket = new Socket("www.google.com", 80, null, 58080);

暫無
暫無

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

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