套接字:使用Java发现端口可用性

时间:2009-01-12 07:38:18

标签: java sockets port

如何使用Java以编程方式确定给定计算机中端口的可用性?

即给出一个端口号,确定它是否已被使用?。

10 个答案:

答案 0 :(得分:87)

这是来自Apache implementation项目的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。

希望这有帮助。

答案 1 :(得分:38)

对于Java 7,您可以使用try-with-resource来获得更紧凑的代码:

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

答案 2 :(得分:35)

从Java 7开始,David Santamaria's answer似乎不再可靠地工作。但是,看起来您仍然可以可靠地使用Socket来测试连接。

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);
            }
        }
    }
}

答案 3 :(得分:32)

如果您不太关心性能,可以尝试使用ServerSocket类来侦听端口。如果它抛出异常,则它正被使用。

public static boolean isAvailable(int portNr) {
  boolean portFree;
  try (var ignored = new ServerSocket(portNr)) {
      portFree = true;
  } catch (IOException e) {
      portFree = false;
  }
  return portFree;
}

编辑:如果你要做的就是选择一个免费端口,那么new SocketServer(0)会为你找到一个。

答案 4 :(得分:8)

以下解决方案的灵感来自Spring-core(Apache许可证)的SocketUtils实现。

与使用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;
    }
}       

答案 5 :(得分:3)

基于try / catch套接字的解决方案可能无法产生准确的结果(套接字地址是“localhost”,在某些情况下,端口可能被“环绕”接口“占用”,至少在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;

答案 6 :(得分: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);              
    }

答案 7 :(得分:0)

在我的情况下,我不得不使用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;

答案 8 :(得分:0)

清除大卫·桑塔玛里亚(David Santamaria)指出的答案:

/**
 * Check to see if a port is available.
 *
 * @param port
 *            the port to check for availability.
 */
public static boolean portIsAvailable(int port) {
    try (var ss = new ServerSocket(port); var ds = new DatagramSocket(port)) {
        return true;
    } catch (IOException e) {
        return false;
    }
}

这仍然受到user207421在对David Santamaria的回答的评论中指出的竞争条件(在此方法关闭ServerSocketDatagramSocket并返回后,某些东西可能会抢占端口)。

答案 9 :(得分:-1)

我尝试了类似这样的东西,它对我很有用

            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");

                 }