2009-01-12 31 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; 
    } 
}