ICMP Ping mit Java und Ausgabe im Fenster PDF Drucken E-Mail
Geschrieben von Administrator   
Monday, 30. March 2009

Den jedem Administrator geläufigen Befehl "ping" gibt es unter Java leider nicht. Er ist aber auf

vielen OS verfügbar, unter anderem unter Linux und Windows. Die folgende Beispiel Applikation

zeigt auf, wie schnell eine Recht geringe Anforderung an eine Applikation die Anwendung

diverser Techniken notwendig macht. Einige der hier angewendeten Techniken sind allerdings

durch elegantere und/oder einfachere Methoden zu ersetzen. Umgekehrt läßt sich aber an

Beispielen wie diesem das Zusammenspiel diverser Techniken auszeigen.

 

Folgendes soll die Applikation tun:

a) Eingaben eines Hostnamens oder einer Host-IP-Adresse in einem JTextField.

b) Überprüfung des lokalen OS

b) Dem OS angepaßter Aufruf eines externen Prozesses, in diesem Fall der "ping"-Befehl.

c) Umlenken der Ausgabe dieses Prozesses in ein JTextArea.

 

Das ganze könnte dann so aussehen:

 

ping example in Java

 

1. Überprüfung des OS:

Java verfügt über zwei Möglichkeiten, das OS festzustellen, unter dem die VM läuft.

Hier soll die Methode

System.getProperty("os.name");

genutzt werden, die einen String zurückliefert, der im Falle eines Windows OS den Substring

"Windows" enthält. Diesen Substring wollen wir mit Hilfe von regular expressions ermitteln, da

dies für spätere Erweiterungen nützlich sein könnte. Momentan  gehen wir aber davon aus, dass

alles was im zurückgegebenen String nicht das Wort "Windows" enthält, Linux ist, Mac-Besitzer

mögen dies verzeihen.

Hier der Code:

 

import java.util.regex.Pattern;
import java.util.regex.Matcher; 
[...]
private boolean winOS = false; // Ist es Windows? Erstmal "nein" antworten 
[...] 
Pattern pattern = Pattern.compile("Windows?"); // Das zu suchende Pattern setzen
Matcher matcher = pattern.matcher(System.getProperty("os.name")); // Den Pattern Matcher setzen
while (matcher.find()) winOS = true; // Ja, es ist Windows

2. Erstellen eines Frames mit JTextArea, JTextField, JButton

Zugegeben: Der Mensch ist faul. Auch ich. Und dies ist kein Swing Tutorial. Als Anregung gebe ich

hier deswegen nur ausschnittsweise den Code wieder, den Netbeans lieferte.

 

private javax.swing.JButton jButton1;    
private javax.swing.JTextArea jTextArea1;
private javax.swing.JTextField jTextField1;
[...]
jTextArea1 = new javax.swing.JTextArea(); 
jTextField1 = new javax.swing.JTextField();
jButton1 = new javax.swing.JButton()
[...]
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jButton1.setText("Ping!");
jButton1.addActionListener(new java.awt.event.ActionListener() {
                                               public void actionPerformed(java.awt.event.ActionEvent evt){      
                                                                 jButton1ActionPerformed(evt);           
                                               }        
                                       }); 

 

Es folgt setzen des Layout, hinzufügen der oben erzeugten Komponenten usw.

 

3. Umlenkung des Standard Outputs auf ein JTextArea

Zur Erinnerung: Jedem PrintStream wird ein OutputStream übergeben. Letzteren erzeugen

wir mit dieser Klasse:

 

class TextAreaOutStream extends OutputStream {

         private JTextArea area = null;        

         TextAreaOutStream (JTextArea out) {            

                  this.area = out;        

         }        

         public void write(final int b) { 

                                                       SwingUtilities.invokeLater(new Runnable() {

                                                                 public void run() {                    

                                                                 area.append(String.valueOf((char)b)); 

                                                                 area.setCaretPosition(area.getText().length()); 

                                                       }            

                                                 });  

}

 

Der Reihe nach:

Es wird ein JTextArea deklariert, danach der Konstruktor erzeugt.

Dieser erfordert die Übergabe des JTextArea, das dem JTextArea Feld der Klasse übergeben wird.

Und dann... oops:

 

Die Methode write(), die von OutputStream geerbet wurde, wird überschrieben.

Die Originalmethode schreibt genau ein Byte in den OutputStream. Die überschreibene,

neue Methode erzeugt eine Thread, der an das übergebene TextArea einen Character

anhängt (via der Methode append des TextArea).

Weiterhin wird der Textzeiger ("Caret") an das Ende des Inhaltes des Textes des TextArea

setzt.

 

Nun fehlt uns noch der PrintStream:

 

Genau wie TextAreaOutStream ist dieser als Inner Class realisiert, und zwar in folgender

abgeleiteter Klasse:

 

class TextAreaStream extends PrintStream {

       TextAreaStream (JTextArea area) {

           super(new TextAreaOutStream(area));

       }

}

 

In alt bekannter Manier wird hier einem PrintStream (über den Konstruktor) ein

OutputStream (bzw. von OutputStream abgeitete Klasse) zugewiesen. Diese abgeleitete

Klasse beinhaltet nun aber die entscheidende Änderung: die write()-Methode wie oben

beschrieben.

 

Am Anfang des Programs wird eine Instanz von TextAreaStream erzeugt und dem Konstruktor

die Referenz auf das JTextArea übergeben und der TextAreaStream als Standardausgabe gesetzt.

 

out = new TextAreaStream(jTextArea1);

System.setOut(out);

 

4. Erzeugen des externen Prozesses

Im Folgenden erzeugen wir einen neuen Prozess. d.h. wir rufen den ping-Befehl auf und

unterscheiden dabei zwischen Windows und Nicht-Windows. Unter Windows werden als Standard

4 Packete gesendet, unter Linux setzen wir die Anzahl explizit auf 4.

Achtung: Unter Linux sind für den ping-Befehl ggf. Rechte zu ändern, bzw. erweiterte Rechte

notwendig!)

 

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)                                        
    {                                            
        if (winOS) // Windows? -> Ja
            processBuilder = new ProcessBuilder("ping", jTextField1.getText() );
        else       // Nein, ist Linux
            processBuilder = new ProcessBuilder("ping", "-c", "4",
                                                        jTextField1.getText() );
        try{
           process = processBuilder.start();

[...]

 

4. Entgegennahme der Ausgabe des externen Prozesses

Bisher zeigt das Programm nur die Konsolenausgaben im JTextArea an, die (direkt oder indirekt)

mit System.out.println o.ä. ausgegeben wurden. Es sollen nun aber die Ausgaben des ping-Befehls

entgegengenommen und in JTextArea sichtbar gemacht werden:

 

 BufferedReader bufferedReader = new BufferedReader(               

                         new InputStreamReader(process.getInputStream()));   // Ausgabestream lesen

String line; 

while ((line = bufferedReader.readLine()) != null) {                               // Und wieder ausgeben

            System.out.print(line+"\n");       

}  

bufferedReader.close();       

 

Soweit ist nun alles implementiert, was das Programm machen sollte. Als letztes noch der Hinweis,

dass eine einfache Abfrage, ob derPing erfolgreich war, durch das Statement

 

if (process.exitValue() == 0)

 

erfolgen kann.

 

 

 

Letzte Aktualisierung ( Tuesday, 31. March 2009 )
 
weiter >