web-dev-qa-db-fra.com

Sockets: Découvrez la disponibilité du port à l'aide de Java

Comment déterminer par programme la disponibilité d'un port sur une machine donnée à l'aide de Java?

i.e étant donné un numéro de port, déterminez s'il est déjà utilisé ou non?.

109
user54075

Ceci est la implémentation venant du projet 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;
}

Ils vérifient également le DatagramSocket pour vérifier si le port est disponible en UDP et TCP.

J'espère que cela t'aides.

87
David Santamaria

Pour Java 7, vous pouvez utiliser try-with-resource pour un code plus compact:

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

Il semble qu'à partir de Java 7, la réponse de David Santamaria ne fonctionne plus de manière fiable. Il semble toutefois que vous puissiez toujours utiliser un Socket de manière fiable pour tester la connexion.

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
TwentyMiles

Si vous n'êtes pas trop préoccupé par les performances, vous pouvez toujours essayer d'écouter sur un port en utilisant la classe ServerSocket S'il y a une exception, il y a de fortes chances qu'il soit utilisé.

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(); */ }
}

EDIT: Si vous essayez uniquement de sélectionner un port libre, new SocketServer(0) en trouvera un pour vous.

30
Spencer Ruport

La solution suivante est inspirée de SocketUtils implémentation de Spring-core (licence Apache).

Comparé à d'autres solutions utilisant Socket(...), il est assez rapide (tester 1000 TCP ports en moins d'une seconde):

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;
    }
}       
6
JMax

Les solutions basées sur les sockets try/catch risquent de ne pas donner des résultats précis (l’adresse du socket est "localhost" et, dans certains cas, le port peut être "occupé" et non pas par l’interface de bouclage et au moins sous Windows, ce test a échoué, par exemple. le prot faussement déclaré comme disponible).

Il y a une bonne bibliothèque appelée SIGAR , le code suivant peut vous connecter:

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;
3
Shmil The Cat

Dans mon cas, il était utile d'essayer de se connecter au port - si le service est déjà présent, il répondrait.

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

Dans mon cas, je devais utiliser la classe 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;
    }
}

N'oubliez pas d'importer d'abord

import Java.net.DatagramSocket;
import Java.net.BindException;
import Java.net.SocketException;
0
kmchmk

Un nettoyage de la réponse signalée par 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;
    }
}

Ceci est toujours soumis à une condition de concurrence critique signalée par l'utilisateur 207421 dans les commentaires à la réponse de David Santamaria (quelque chose pourrait saisir le port après que cette méthode ferme les variables ServerSocket et DatagramSocket et les renvoie).

0
Luke Hutchison