2010-07-16 50 views
6

我明白,下面的代碼可以(也許不是很有效)找出Java的免費的TCP端口:找到兩個免費的TCP端口

public static int findFreePort() { 
    int port; 
    try { 
     ServerSocket socket= new ServerSocket(0); 
     port = socket.getLocalPort(); 
     socket.close(); 
    } catch (Exception e) { port = -1; } 
    return port;  
    } 

(這裏有一些相關的問題,在SO - forexample) 。

我不明白的是爲什麼(或者是否)對這個方法的兩次連續調用都保證返回兩個不同的端口。假定這是例如here(搜索findFreePort方法的呼叫)。

這是正確的嗎?對於ServerSocket的

+0

如果有相關的問題,你應該引用它們並鏈接到它們。 – Freiheit 2010-07-16 14:25:53

+0

@Freiheit:完成 – leonbloy 2010-07-16 14:29:59

+0

由於SO_WAIT,這個機制沒有被重新分配,這個機制旨在規避一個仍然在傳輸中的數據包將被另一個進程接收。默認情況下,關閉TCP端口後,在接下來的2分鐘內不會重新分配以允許這些延遲的數據包刷新。 – 2014-09-16 14:53:50

回答

5

在Javadoc規範,我看不出有任何行說兩個succesive調用保證返回兩個不同的端口...

由於ServerSocket的關閉,第二個電話可以給同一個端口。從統計的角度來看,我認爲這是不可能的,但不是不可能的。

如果你打開你的兩個ServerSocket,得到端口,然後關閉你的兩個ServerSocket,你會得到兩個不同的端口(因爲當你創建第二個ServerSocket時,第一個不是免費的)。

實例方法來獲取n個不同的自由港:

public int[] getFreePorts(int portNumber) throws IOException { 
    int[] result = new int[portNumber]; 
    List<ServerSocket> servers = new ArrayList<ServerSocket>(portNumber); 
    ServerSocket tempServer = null; 

    for (int i=0; i<portNumber; i++) { 
     try { 
      tempServer = new ServerSocket(0); 
      servers.add(tempServer); 
      result[i] = tempServer.getLocalPort(); 
     } finally { 
      for (ServerSocket server : servers) { 
       try { 
        server.close(); 
       } catch (IOException e) { 
        // Continue closing servers. 
       } 
      } 
     } 
    } 
    return result; 
} 
+0

是的,我剛剛編碼幾乎完全相同的方法:-) – leonbloy 2010-07-17 14:05:52

+1

應該指出,即使這種解決方案(和諾埃爾M的)不是100%萬無一失,有潛在的競爭條件。在此方法調用之後,調用者將最終嘗試使用這些可用端口。但在此期間可能會發生一些其他進程打開它的情況。 – leonbloy 2010-07-17 14:14:12

0

源代碼是在這裏:http://kickjava.com/src/java/net/ServerSocket.java.htm

我不太看到它是如何確定該端口是否空閒,但:

@param port the port number, or <code>0</code> to use any 
free port. 

所以一旦第一個端口分配,即使是你的應用程序,它不再是免費的。所以連續調用ServerSocket將不會重用該端口,從而保證兩個不同的端口。

+0

但'findFreePort'打開套接字並立即關閉它,因此理論上再次可用。 – leonbloy 2010-07-16 14:52:43

+0

在代碼中,分配端口,但「close()」方法取消分配此端口。然後,它可以被重用(例如由另一個ServerSocket)。所以,我認爲對該方法的另一個調用可能會給出相同的端口號。 – 2010-07-16 14:53:30

2

一種方式來獲得兩個不同的端口號:

ServerSocket socket1= new ServerSocket(0); 
    port1 = socket.getLocalPort(); 
    ServerSocket socket2= new ServerSocket(0); 
    port2 = socket.getLocalPort(); 

    socket1.close(); 
    socket2.close(); 
0

這是一樣有效,操作系統可以做到這一點。然而,之後立即關閉ServerSocket是沒有意義的,因爲該端口不再被保留,並且可以分配給其他內容。這個練習的唯一目的是創建一個ServerSocket,所以就創建它。

0

這是我用來查找多個空閒端口的類。它爲在一些複雜邏輯流程中分配單個端口提供了靈活性(即,可能需要的端口數量不是簡單的數量,而是取決於複雜的邏輯)。它仍然保證你所要求的所有端口都是免費且唯一的(只要你使用這個類的同一個實例來獲得所有的端口)。

所以使用這個類的方法是創建一個實例。執行您的代碼以執行您想要爲使用該實例分配端口的任何操作。然後,一旦你綁定了所有的端口,你就可以處理這個實例並下次使用新的實例。

public class PortFinder { 

/** 
* If you only need the one port you can use this. No need to instantiate the class 
*/ 
public static int findFreePort() throws IOException { 
    ServerSocket socket = new ServerSocket(0); 
    try { 
     return socket.getLocalPort(); 
    } finally { 
     try { 
      socket.close(); 
     } catch (IOException e) { 
     } 
    } 
} 

private HashSet<Integer> used = new HashSet<Integer>(); 

/** 
* Finds a port that is currently free and is guaranteed to be different from any of the 
* port numbers previously returned by this PortFinder instance. 
*/ 
public synchronized int findUniqueFreePort() throws IOException { 
    int port; 
    do { 
     port = findFreePort(); 
    } while (used.contains(port)); 
    used.add(port); 
    return port; 
} 

} 
+0

其中是findFreePort(); 方法。 @Kris – Roster 2015-09-14 11:11:46

+0

它就在那裏,PortFinder類的第一個成員。也許我通過把它放在現場聲明之前的不尋常的順序來混淆事物。 – Kris 2015-09-15 21:07:41