2009-01-12 29 views
101

如何以編程方式確定使用Java的給定計算機中端口的可用性?套接字:使用Java發現端口可用性

即給出一個端口號,確定它是否已被使用?

+2

雖然這個問題是關於如何知道如果給定的端口已在使用,你可能已經降落在這裏試圖找到一種方法來獲得一個免費的端口號,這http://stackoverflow.com/questions/2675362/how-to-find-an-available-port(連接到我的https://要點.github.com/3429822)涵蓋更好。 – vorburger 2012-08-22 22:12:20

+0

爲了什麼目的?如果你只是想找一個空的套接字來聽,只需指定零。任何掃描技術都有可能出現計時窗口問題:當您掃描時端口可能是空的,並且當您去索賠時佔用端口。 – EJP 2016-02-28 19:38:05

回答

30

如果您不太關心性能,您可以嘗試使用ServerSocket類嘗試收聽端口。如果它拋出一個異常,它正被使用。

boolean portTaken = false; 
    ServerSocket socket = null; 
    try { 
     socket = new ServerSocket(_port); 
    } catch (IOException e) { 
     portTaken = true; 
    } finally { 
     if (socket != null) 
      try { 
       socket.close(); 
      } catch (IOException e) { /* e.printStackTrace(); */ } 
} 

編輯:如果你試圖做的是選擇一個空閒的端口,然後new SocketServer(0)會找到一個適合你。

+0

最後使用清理(嘗試{...}最後{{}} {{ socket.close();} – 2009-01-12 07:51:34

+0

你也可以設置「portTaken =(socket == null);」而不是在catch中做這個 – 2009-01-12 07:52:29

+0

這試圖綁定到socket上的所有0.0.0.0)interfaces。您可以使用顯式地址來檢查特定地址上的特定端口。請參閱http://java.sun.com/j2se/1.4.2/docs/api/java/net/ServerSocket.html#ServerSocket( int,%20int,%20java.net.InetAddress) – cletus 2009-01-12 08:32:07

82

這是implementation從Apache camel項目未來:

/** 
* Checks to see if a specific port is available. 
* 
* @param port the port to check for availability 
*/ 
public static boolean available(int port) { 
    if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) { 
     throw new IllegalArgumentException("Invalid start port: " + port); 
    } 

    ServerSocket ss = null; 
    DatagramSocket ds = null; 
    try { 
     ss = new ServerSocket(port); 
     ss.setReuseAddress(true); 
     ds = new DatagramSocket(port); 
     ds.setReuseAddress(true); 
     return true; 
    } catch (IOException e) { 
    } finally { 
     if (ds != null) { 
      ds.close(); 
     } 

     if (ss != null) { 
      try { 
       ss.close(); 
      } catch (IOException e) { 
       /* should not be thrown */ 
      } 
     } 
    } 

    return false; 
} 

他們正在檢查的DatagramSocket類以及檢查端口處於UDP和TCP avaliable。

希望這會有所幫助。

0

在我的情況下,它有助於嘗試連接到端口 - 如果服務已經存在,它會作出響應。

try { 
     log.debug("{}: Checking if port open by trying to connect as a client", portNumber); 
     Socket sock = new Socket("localhost", portNumber);   
     sock.close(); 
     log.debug("{}: Someone responding on port - seems not open", portNumber); 
     return false; 
    } catch (Exception e) {   
     if (e.getMessage().contains("refused")) { 
      return true; 
    } 
     log.error("Troubles checking if port is open", e); 
     throw new RuntimeException(e);    
    } 
31

看來,從Java 7開始,David Santamaria's answer不再可靠工作。但是,看起來您仍然可以可靠地使用套接字來測試連接。

private static boolean available(int port) { 
    System.out.println("--------------Testing port " + port); 
    Socket s = null; 
    try { 
     s = new Socket("localhost", port); 

     // If the code makes it this far without an exception it means 
     // something is using the port and has responded. 
     System.out.println("--------------Port " + port + " is not available"); 
     return false; 
    } catch (IOException e) { 
     System.out.println("--------------Port " + port + " is available"); 
     return true; 
    } finally { 
     if(s != null){ 
      try { 
       s.close(); 
      } catch (IOException e) { 
       throw new RuntimeException("You should handle this error." , e); 
      } 
     } 
    } 
} 
35

對於Java 7,你可以使用try-與資源用於更緊湊的代碼:

private static boolean available(int port) { 
    try (Socket ignored = new Socket("localhost", port)) { 
     return false; 
    } catch (IOException ignored) { 
     return true; 
    } 
} 
3

的try/catch語句插座基礎的解決方案,可能不會產生準確的結果(套接字地址是「本地主機「並且在某些情況下,端口可能不被回送接口」佔用「,並且至少在Windows上我已經看到這個測試失敗,也就是說虛假聲明爲可用)。

SIGAR名爲酷庫,下面的代碼可以幫你搞到:

Sigar sigar = new Sigar(); 
int flags = NetFlags.CONN_TCP | NetFlags.CONN_SERVER | NetFlags.CONN_CLIENT;    NetConnection[] netConnectionList = sigar.getNetConnectionList(flags); 
for (NetConnection netConnection : netConnectionList) { 
    if (netConnection.getLocalPort() == port) 
     return false; 
} 
return true; 
0

我已經試過這樣的事情,它的工作非常細跟我

  Socket Skt; 
      String host = "localhost"; 
      int i = 8983; // port no. 

       try { 
        System.out.println("Looking for "+ i); 
        Skt = new Socket(host, i); 
        System.out.println("There is a Server on port " 
        + i + " of " + host); 
       } 
       catch (UnknownHostException e) { 
        System.out.println("Exception occured"+ e); 

       } 
       catch (IOException e) { 
        System.out.println("port is not used"); 

       } 
-1

在我的案例我不得不使用DatagramSocket類。

boolean isPortOccupied(int port) { 
    DatagramSocket sock = null; 
    try { 
     sock = new DatagramSocket(port); 
     sock.close(); 
     return false; 
    } catch (BindException ignored) { 
     return true; 
    } catch (SocketException ex) { 
     System.out.println(ex); 
     return true; 
    } 
} 

不要忘了導入第一

import java.net.DatagramSocket; 
import java.net.BindException; 
import java.net.SocketException; 
1

下面的解決方案是由SocketUtils實現Spring的核心(Apache許可證)的啓發。

與使用Socket(...)這是相當快的其他解決方案(測試在更短的1000個TCP端口超過一秒):

public static boolean isTcpPortAvailable(int port) { 
    try (ServerSocket serverSocket = new ServerSocket()) { 
     // setReuseAddress(false) is required only on OSX, 
     // otherwise the code will not work correctly on that platform   
     serverSocket.setReuseAddress(false); 
     serverSocket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), port), 1); 
     return true; 
    } catch (Exception ex) { 
     return false; 
    } 
}