Problème ping + lancement (ou arret) programme (fini]

Bonjour,

Voici le code que j ai récupéré sur internet pour l’exécution du ping:




import java.net.* ;
import java.io.* ;


class Ping {

    static int port = 6758 ;

    public static void main (String[] args) {
        try {
            if (args.length == 0) {

                // -------------- Repondre aux pings

                DatagramSocket sock = new DatagramSocket (port) ;
                while (true) {
                    pong (sock) ;
                }

            } else if (args.length == 1) {

                // ------------- Faire des pings.

                DatagramSocket sock = new DatagramSocket (port+1) ;
                // Un port différent permet de tester sur la meme machine.
                InetAddress ip = InetAddress.getByName ("serveur") ;

                // Tous les paquets seront envoyes vers et recus de :
                sock.connect (ip, port) ;
                sock.setSoTimeout(1) ;
                while (true) {
                    try {
                        ping (sock) ;
                    } catch (SocketTimeoutException e) {
                        System.out.println ("la reponse tarde") ;
                    }
                    Thread.sleep (1000) ;
                }

            } else {
                throw new Exception ("Usage:\n java Ping : repond aux pings.\n java Ping ip :  fait des pings vers l'adresse ip.\n") ;
            }

        } catch (SocketException e) {
            System.err.println ("Port " + port
                            + " ou " + (port+1) + " déjà pris ?") ;
        } catch (UnknownHostException e) {
            System.err.println ("Machine inconnue : " + args[0]) ;
        } catch (Exception e) {
            System.err.println (e) ;
        }
    }

    static byte[] buf = new byte [512] ;
    static DatagramPacket p = new DatagramPacket (buf, 512) ;

    static void pong (DatagramSocket sock) throws IOException {
        sock.receive (p) ;
        InetAddress ip = p.getAddress () ;
        int port = p.getPort () ;
        int count = readInt16 (buf, 0) ;
        System.out.println ("ping " + count + " from " + ip + ":" + port) ;
        // On renvoie p `a l'expediteur :
        p.setAddress (ip) ;
        p.setPort (port) ;
        sock.send (p) ;
    }

    static int count = 0 ;

    static void ping (DatagramSocket sock) throws IOException {
        // buf est le contenu de p
        writeInt16 (buf, 0, count) ;
        sock.send (p) ;
        System.out.println ("ping " + count + " envoye") ;
        // Incr'ementer le compteur :
        count++ ;
        // On attend le retour :
        sock.receive (p) ;
        int count = readInt16 (buf, 0) ;
        System.out.println ("     " + count + " bien recu") ;
    }

    static void writeInt8 (byte[] buf, int pos, int i) {
	buf [pos] = (byte) i ;
    }

    static void writeInt16 (byte[] buf, int pos, int i) {
	writeInt8 (buf, pos, i / 256) ; // high order byte first = big endian
	writeInt8 (buf, pos+1, i % 256) ;        
    }

    static int readInt8 (byte[] buf, int pos) {
	return (256 + buf [pos]) % 256 ;
    }

    static int readInt16 (byte[] buf, int pos) {
	return 256 * readInt8 (buf, pos) + readInt8 (buf, pos+1) ;
    }

}

Au niveau de l’ip, je lui ai dit de récupérer l’adresse du serveur. Mais quand je le lance le programme avec Eclipse rien ne se passe…

Ai je oublié quelque chose?

merci d’avance


Dans un second temps:

Lors de la non détection du ping, je voudrais arreter un programme (voire 2) puis les relancer.

Problème:
Ces programmes sont du java, donc pour les arreter soit j’arrete tous les processus javaw présent, soit je les ferme les un après les autres.

Mais si je ferme javaw, fe ferme aussi le gestionnaire du ping iniateur de cette fermeture.

comment puis je faire? y a t il une solution?

merci
Edité le 21/08/2007 à 08:41

pub?

Oublie ça Florent42.

Pour ta question 2, tout ton problème est de communiquer avec les autres programmes. Tu as plusieurs choix, comme les mettre en attente de message sur un port quelconque, ou les signaux, etc.

oui effectivement je vois ce que tu veux dire

mettre un port en ecoute pour les commandes de maintenance…oui pourquoi pas.

Mais un port par prog, ça risque d’êtr difficile àgérer.

pour ton 1er problème: vérifie que tu a bien un argument de ligne de commande pour lancer le ping (qui est testé dans le main) dans l’entrée “run…” d’éclipse"

pour le 2ème:
Comment tu les arrête?: s’ils sont lancés en ligne de commande tu peut les couper par crtl-C
un autre solution serait de lancer tes pings dans le même programme: plutôt que tout faire dans le main, faire une petite fonction ping sur laquelle tu boucle, ou que tu lance en Thread.
et s’il faut que tu en lance de nouveau tu peut effectivment avoir un port type telnet pour a la fois ouvrir et fermer des ping (en coupant uniquement le Thread)

Sinon, tu peux faire un kill ou équivalent Windows; suffit que tes sous processus java sauvegardent dans un fichier leur pid… et que tu ailles lire ce pid, et les tuer (envoi de signaux en java, je sais pas si c’est possible).

  1. quand j’indique un argument dans le run d’eclipse j ai effectivement un petit changement

Quand je met serveur ou 192.168.120.2, il me répond dans la console:
ping 0 envoye
Port 6758 ou 6759 déjà pris ?

j’ ai essaye avec un autre port 10058 ca a fait pareil
Pourtant je n’ai pas de firewall rien du totu de ce genre qui pourait bloquer

  1. je ne connais pas suffisement le java pour modifier les programmes java existant et d’utiliser les threads…
    Oui sous Windows j’avais déjà faire des recherchers taskkill peut arreter un process soit avec le nom soit avec le PID. Il suffira pour cela de lancer via java une commande DOS

Qu en pensez vous?

La valeur de l’argument que tu passe en ligne de commande n’est pas utilisé, seule sa présence oui./non est utisé.

Donc tu cherche en dur dans le programme “serveur” port 6758 .et (6758+1) pour l’adresse locale d’origine: mais tu peux enlever l’argument, il va chercher un port libre tout seul:



 // ------------- Faire des pings.  
DatagramSocket sock = new DatagramSocket (/* rien ici */) ;

le problème reste entier

il bloque toujours au meme endroit sans aller plus loin

C’est pas ça du tout, le message d’erreur n’a rien à voir avec l’erreur, ça veut juste dire qu’il ne peut pas ouvrir la socket parce que personne n’ecoute de l’autre côté sur la socket en question i.e. tu n’as pas lancé le pong sur la machine s’appelant “serveur”.

Et là ou c’est tricky, c’est qu’on ne s’en rend compte qu’à la 1ère écriture, vu que l’UDP fonctionne en mode “non connecté”, donc le connect ne fait rien sur le réseau en fait :smiley:

edit: tout ça pour dire: je l’ai lancé sur mon poste, remplacé “serveur” par “localhost” et ça marche très bien si tu lance “pong” avant “ping”
Edité le 07/08/2007 à 15:24

ca veut dire qu il faut lancer ce programme 2 fois et fonctionne donc a la fois sur un serveur et un client???

ca va pas du tout ca…

Dans mon cas, le systeme dont je vais tester le ping n’est pas un PC…j’aurais du mal a lui installer le programme java :frowning:

Y a pas moyen de faire un ping sur l’adresse que je veux et avoir le retour “classique” et detecter si le retour est bon ou si il y a un problème et donc je fais une action (relance de programmes dans mon cas) ?
et le tout sa avoir besoin d’ouvrir un port d’écoute sur l’équipement distant

Bonjour
ah oui, ça remet tout en cause, ton programme n’implémente pas le vrai “Ping” du protocole ICMP, le seul accessible par défaut sur les périphériques IP, sous réserve qu’il ne soit pas désactivé. d’ailleurs en Java, c’est un peu difficile à faire: ce n’est ni de l’UDP ni du TCP. (les 2 Sockets de base en Java)

bref essaye déjà en ligne de commande si ton serveur est pingable, puis éventuellement lance le ping avec un Runtime.exec, ou alors essaye de trouver un bib qui fasse le vrai ping ICMP en Java.

enfin ton faux Ping, tu pourrais toujours l’installer sur ton serveur en question s’il a un système UNIX avec une jvm installée?

bonjour a tous,

Je suis parti sur un autre code trouvé sur internet que j ai modifié et adapté à mon cas le voici complet en 2 pages:

Analyserreseau.java:


import java.util.ArrayList;
import java.util.Date;
 
public class AnalyserReseau {
		
	public static void main(String[] args) {
 
		int i;
		for(i=0;i< 50000000 ;i++)
		{
		//Liste de tous les machines/sites a tester
		ArrayList<ThreadPing> maListe = new ArrayList<ThreadPing>();
		maListe.add(new ThreadPing("192.168.120.251"));	//sera OK	

		
		//debut des Ping sachant qu'il y a des sites ou ça va foirer !!!
		Date dateDebut = new Date();


			for( ThreadPing tp : maListe)
				{
				tp.start() ;
				}
				
			try
				{
				for( ThreadPing tp : maListe)
					{
					tp.join() ;
					}
				}
				catch(InterruptedException ie)
					{
					ie.printStackTrace();
					}
			Date dateFin = new Date();
			//fin ping
			long diff = dateFin.getTime() - dateDebut.getTime();
			System.out.println("Tps execution => "+diff);
			
			try 
				{
				Thread.sleep(5000);
				} 
				catch (InterruptedException e) 
				{
				// TODO Auto-generated catch block
				e.printStackTrace();
				} 
			}
		
	}
 
}
 
 

ThreadPing.java


import java.io.IOException;
import java.net.InetAddress;
import java.util.Properties;


 
public class ThreadPing extends Thread 
{
	private String nom  ;
	private boolean pingOK = false ;
	private final int tpsTimeOut = 2000;
	
	public ThreadPing( String nomMachineATester )
	{
		this.nom = nomMachineATester ;
	}
	
	public void run()
	{
		try{
			InetAddress i = InetAddress.getByName(nom);
			pingOK = i.isReachable(this.tpsTimeOut);
			if(pingOK)
				{
				System.out.println(this.nom +" => OK");
				}
			else
			{
				System.out.println(this.nom +" => ECHEC !!!");
				Thread.sleep(5000);
		        Properties sys = System.getProperties();
		        String os = sys.getProperty("os.name");
		        Runtime r = Runtime.getRuntime();
		        if (os.endsWith("2000"))
		        	{
		        	r.exec("kill javaw");
		        	}
			        else
			        	r.exec("taskkill javaw");
			}
			}
		catch(Exception e)
		{
			e.printStackTrace();}

		
	}
	
	public boolean isPingOk()
	{
		return this.pingOK ;
	}
}
 
 

ce code fonctionne parfaitement et detecte tres bien le “serveur” si il OK ou bien entrain de redemarrer par exemple et donc m’envoi l’info “ECHEC”.

J’ai rajouter une boucle for pour qu il me fasse un test de façon régulière. Et en cas d’échec, il arrete les processus javaw. Je n’ai pas encore implémenté leur redémarrage.

Avec tout ca j ai deux questions:

  • pour l’instant au niveau de cette boucle de vérification, j ai mis un grand nombre…mais peut on en faire une vérification permanente et perpetuelle? (style boucle infinie)

  • Avec l’arret des process javaw, on en arrive au problème que je craignais c’est a dire que ca vire le programme que je veux…et lui meme
    Je pense que l’idée de sans-nom est encore la plus simple a réaliser qui consistait a ecrire au lancement des applications leur PID dans un fichier.
    Mais comment récupérer ce PID?

merci d’avance

“isReachable”, il faut que je me le mette dans la tête, je ne connaissais pas.
mais pourquoi tu ferme des process javaw, tu n’en lance pas? c’est au lancement du process que tu peux avoir son PID.

d’après ce que j ai vu sur isreachable…il faut s’en méfier

j’ai lu un forum la dessus et apparement (je n ai pas testé encore) il faut avoir des pouvoirs pour l’utiliser sur un Windows (style administrateur)…j en sais pas plus pour l’instant

En fait j ai lancé tout ca depuis Eclipse. Jusqu’a la pas de soucis. J’ai bien dans ma liste de process que j avais 2 javaw lancé.
Normal: celui que utilise Eclipse pour lancer mon programme et mon autre programme

or dans le code je demande de faire un kill de javaw…résultat il me ferme tout javaw
Mais le programme du départ venant d’Eclipse est également fermé! donc impossible de réouvrir quoique ce soit !


Au lancement comment peut on avoir le PID?

Le programme la est un controleur rien de plus.

Pour l’utilisateur final, il aura un fichier qui lancera (en masqué , merci sans-nom) ce que je veux et c est a ce moment la que je voudrais récupérer le PID de ce qui sera lancé. Le tout mettre dans 1/2/ ou 3 fichiers et en cas de problème, le “controleur” lira les fichiers des process qui doivent etre relancé, les “killera” et les relancera

une question qui me vient comme ca…peut on mélanger dans un r.exec(); du dos avec des variables java? oui parce que le PID ainsi récupéré, il faudra que je l’envoi la dedans…


mouai je viens de me souvenir que oui c 'était possible puisque je l'avais déjà fait...on oublie ma derniere question désolé :)

Ce que je voulais dire: enlève ces fameux kill, et regarde si le nombre de process augmente, sinon, c’est que c’est OK comme ça (puisque tu ne lance pas de javaw par runetime exec, il n’y a pas de raison qu’il s’en crée de nouveaux)

sinon, pour répondre à la question:

tasklist /fi "IMAGENAME eq javaw.exe" 

te renvoie tous les process java, à trier par PID, les plus grands sont les derniers créés.
Edité le 08/08/2007 à 16:04

mais je serais obligé de “relancer” les programmes par r.exec…

on peut appeler des programmes java autrement que par r.exec?(et l habituel javaw -jar prg.jar?)

Non, r.exec c’est juste une bidouille pour forcer java à lancer des programmes systèmes. là tu lance des Thread, pas des process.

comment peut on alors lancer un programme jar d’un meme programme java?

Tu peux appeler le main de la classe depuis un Thread, mais je ne comprend pas, pourquoi aurais-tu besoin de faire ça?
Avec le dernier listing que tu nous as envoyé, tu crée autant de Thread que de machine à tester, et tu boucle (presque) indéfiniment, le tout directement dans ton programme, rien besoin de lancer d’autre :neutre:

Pour la boucle infinie, c’est

 "while(true){
/*code*/
}
//ou alors 
for(;;){
/*code*/
}

Je préfère le while, aussi efficace et plus lisible.