16.15 Internet Control Message Protocol (ICMP)
Neben dem Internet-Protokoll werden noch mehrere Steuerprotokolle auf der Vermittlungsschicht eingesetzt. Darunter befindet sich auch das Internet Control Message Protocol (ICMP), das im Prinzip ein IP-Paket mit bestimmten Flags ist. Dieses ist im RFC 792 definiert. Da das Funktionieren des Internets sehr stark von Routern abhängt, wurde ICMP entwickelt, um unerwartete Ereignisse und Zusatzinformationen zu melden. Java unterstützt zur Zeit nur Sockets vom Typ SOCK_STREAM (TCP) und SOCK_DGRAM (UDP), aber keine IP-Pakete (und damit auch nicht das Internet Control Message Protocol) mit dem Sock-Typ SOCK_RAW. Daher können in Java mit den Standardbibliotheken keine IP-Pakete und ICMP-Nachrichten verschickt werden. Für die kommende Version 1.5 ist eine Unterstützung angekündigt. Damit ergeben sich aber auch neue Rechts- und Sicherheitsprobleme. Viele Unix-Systeme erlauben Sockets vom Typ SOCK_RAW nur unter Root-Rechten.
16.15.1 Ping
Da Dienste wie »ping« oder »traceroute« auf ICMP aufbauen, ist eine Implementierung dieser Tools in Java momentan nicht möglich und so muss auf JNI zurückgegriffen werden. Eine Lösung unter Windows stammt von Isabel García und Óscar Fernández, die unter http://www.geocities.com/SiliconValley/Bit/5716/ping/index_eng.html eine Bibliothek (ohne Quellcode) zur Verfügung stellen. Eine native Bibliothek ist nötig (pingicm.dll), denn sonst könnten keine ICMP-Pakete versendet werden.
Ein Ping-Programm besteht im Wesentlichen aus der Initialisierung der Klasse, dem Absenden eines Pings und dem Empfang eines Pongs. Das empfangene Datenpaket liegt dabei in einem String-Feld aus vier Werten, in denen dann Zeit und IP-Adressen des Partners liegen:
String dataRcv[] = new String[4];
PingICMP ping = new PingICMP();
ping.begin();
if ( ping.ping("127.0.0.1", 5, 1) )
{
ping.pong( dataRcv );
System.out.println( "Host: " + dataRcv[0] +
" ping time: " + dataRcv[3] );
}
final class estadisticas.icmp.PingICMP
|
|
PingICMP () |
|
Erzeugt ein neues PingICMP-Objekt. |
|
final boolean begin () |
|
Initialisiert den Socket zum Senden und Empfangen. Nur genau ein Socket darf offen sein. Der Rückgabewert ist false, falls der Socket nicht initialisiert werden konnte. |
|
final boolean end () |
|
Schließt den Socket, so dass später noch einmal mit begin() eine Sitzung eröffnet werden kann. Der Rückgabewert ist false, falls der Socket nicht geschlossen werden konnte. |
|
final boolean ping( String address, int identifier, int seqNumber ) |
|
Sendet ein ping an die IP-Adresse des Empfängers. Der Identifizierer ist wie die Sequenznummer eine Zahl zwischen 0 und 65.535. Der Rückgabewert ist false, falls das Paket nicht versendet werden konnte oder ein Parameter falsch ist. |
|
final boolean pong( String results[] ) |
|
Die Funktion wartet so lange blockierend, bis ein Echo eintrifft. Das bestehende Feld wird mit vier Werten gefüllt. Der erste Wert ist die IP-Adresse der entfernten Maschine, dann folgt die Identifikation, die Sequenznummer und an Position drei die Ping-Zeit. Die Rückgabe ist false, falls ein Fehler auftritt oder das Feld nicht mindestens vier Elemente fasst. ping()/pong() sollte mehrmals aufgerufen werden, damit die Zeiten repräsentativ sind. |
|