Galileo Computing < openbook >
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


Java ist auch eine Insel (2. Aufl.) von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 1.4
Java ist auch eine Insel (2. Auflage)
gp Kapitel 16 Netzwerkprogrammierung
  gp 16.1 Grundlegende Begriffe
  gp 16.2 URL-Verbindungen und URL-Objekte
    gp 16.2.1 Die Klasse URL
    gp 16.2.2 Informationen über eine URL
    gp 16.2.3 Der Zugriff auf die Daten über die Klasse URL
  gp 16.3 Die Klasse URLConnection
    gp 16.3.1 Methoden und Anwendung von URLConnection
    gp 16.3.2 Protokoll- und Content-Handler
    gp 16.3.3 Im Detail: von URL zu URLConnection
    gp 16.3.4 Autorisierte URL-Verbindungen mit Basic Authentication
  gp 16.4 Das Common Gateway Interface
    gp 16.4.1 Parameter für ein CGI-Programm
    gp 16.4.2 Kodieren der Parameter für CGI-Programme
    gp 16.4.3 Eine Suchmaschine ansprechen
  gp 16.5 Host- und IP-Adressen
    gp 16.5.1 Klasse-K-Netz
    gp 16.5.2 IP-Adresse des lokalen Hosts
    gp 16.5.3 Die Methode getAllByName()
  gp 16.6 NetworkInterface
  gp 16.7 IPv6 für Java mit Jipsy
  gp 16.8 Socket-Programmierung
    gp 16.8.1 Das Netzwerk ist der Computer
    gp 16.8.2 Standarddienste unter Windows nachinstallieren
    gp 16.8.3 Stream-Sockets
    gp 16.8.4 Informationen über den Socket
    gp 16.8.5 Mit telnet an den Ports horchen
    gp 16.8.6 Ein kleines Echo – lebt der Rechner noch?
  gp 16.9 Client/Server-Kommunikation
    gp 16.9.1 Warten auf Verbindungen
    gp 16.9.2 Ein Multiplikations-Server
  gp 16.10 SLL-Verbindungen mit JSSE
  gp 16.11 Webprotokolle mit NetComponents nutzen
  gp 16.12 E-Mail
    gp 16.12.1 Wie eine E-Mail um die Welt geht
    gp 16.12.2 Übertragungsprotokolle
    gp 16.12.3 Das Simple Mail Transfer Protocol
    gp 16.12.4 E-Mails versenden mit Suns JavaMail-API
    gp 16.12.5 E-Mails mittels POP3 abrufen
  gp 16.13 Arbeitsweise eines Webservers
    gp 16.13.1 Das Hypertext Transfer Protocol (HTTP)
    gp 16.13.2 Anfragen an den Server
    gp 16.13.3 Die Antworten vom Server
  gp 16.14 Datagram-Sockets
    gp 16.14.1 Die Klasse DatagramSocket
    gp 16.14.2 Datagramme und die Klasse DatagramPacket
    gp 16.14.3 Auf ein hereinkommendes Paket warten
    gp 16.14.4 Ein Paket zum Senden vorbereiten
    gp 16.14.5 Methoden der Klasse DatagramPacket
    gp 16.14.6 Das Paket senden
    gp 16.14.7 Die Zeitdienste und ein eigener Server und Client
  gp 16.15 Internet Control Message Protocol (ICMP)
    gp 16.15.1 Ping
  gp 16.16 Multicast-Kommunikation


Galileo Computing

16.4 Das Common Gateway Interface  downtop

CGI (Common Gateway Interface) ist eine Beschreibung einer Schnittstelle http://cgi-spec.golux.com/, mit der externe Programme mit Informationsservern, meistens Webservern, Daten austauschen. Die aktuelle Version ist CGI/1.1. Diese ausgeführten Programme werden kurz CGI-Programme genannt und können in allen erdenklichen Programmiersprachen verfasst sein. Häufig sind es Shell-/Python- oder Perl-Skripte (oft wird dann die Bezeichnung CGI-Skripte verwendet). Die Unterscheidung zwischen Skript und Programm ist bei CGI schwammig. Traditionell ist eine kompilierte Quelldatei ein Programm, und Programme, die mit einem Interpreter arbeiten, ein Skript. Wir werden im Folgenden allerdings »Programm« und »Skript« synonym verwenden. Für uns ist es erst einmal egal, ob ein Programm oder ein Skript ausgeführt wird. Denn wir wollen diese Programme aus Java nutzen und nicht selber schreiben. Auf der Serverseite ergänzen und verdrängen Java Server Pages beziehungsweise Servlets immer stärker CGI-Programme.

Die CGI-Programme werden von einem Browser durch eine ganz normale URL angesprochen. Der Browser baut eine Verbindung zum Server auf und dieser erkennt anhand des Pfads oder anderer Kriterien (Dateiendung oder spezielle Dateiflags), ob es sich um eine ganz normale Webseite handelt oder um ein Skript. Wenn es ein Skript ist, dann führt der Server das Skript aus, welches eine HTML-Datei erzeugt. Diese wird übertragen und im Browser dargestellt. Der Aufrufer einer URL merkt keinen Unterschied (außer vielleicht in der Performance) zwischen erstellten, also dynamischen, und statischen Seiten. Die CGI-Programme sind also immer eine Angelegenheit des Servers, der uns mit aktuellen Daten versorgt.


Galileo Computing

16.4.1 Parameter für ein CGI-Programm  downtop

Beim Aufruf eines CGI-Programms können Parameter übergeben werden, bei einer Suchmaschine etwa der Suchbegriff. Es gibt nun zwei Möglichkeiten, wie diese Parameter zum Skript kommen und somit vom Webserver verarbeitet werden.

gp  Die Parameter (auch Query-Strings genannt) werden an die URL angehängt (GET-Methode). Das Skript liest die Daten aus der CGI-Umgebungsvariablen QUERY_STRING aus.
gp  Die Daten werden zur Standardeingabe des Webservers gesendet (POST-Methode). Das Skript muss dann aus dieser Eingabe lesen.

GET und POST unterscheiden sich auch in der Länge der übertragenen Daten. Bei vielen Systemen ist die Länge einer GET-Anfrage beschränkt auf 1024 Byte. POST-Anfragen sind längenunbegrenzt.

Daten werden nach der GET-Methode verschickt

Die Daten sind mit dem CGI-Programmnamen verbunden und gehen beide zusammen auf die Reise. Der Anfrage-String (Query-String) wird hinter ein Fragezeichen gesetzt, das Et-Zeichen »&« trennt mehrere Anfragezeichenketten. Unter Java setzen wir einfach einen Befehl ab, indem wir ein neues URL-Objekt erzeugen und anschließend den Inhalt auslesen:

meineURL = new URL( "http", "...", "cgi-bin/trallala?tri" );

Das CGI-Skript holt sich seinerseits die Daten aus der Umgebungsvariablen QUERY_STRING. Das folgende Kapitel zeigt, wie diese Abfragezeichenketten komfortabel durch die Klasse URLEncoder zusammengebaut werden. Werfen wir jedoch erst einen Blick auf die Variablen.

Daten holen mit der POST-Methode

Die Klasse URLConnection bietet die schon bekannte Methode getOutputStream() an, die eine Verbindung zur Eingabe des CGI-Scripts möglich macht (POST-Methode):

// CGI-Script schickt die Daten zurück

PrintStream o = new PrintStream( cgiConnection.getOutputStream() );
o.println( data );
o.close();

Galileo Computing

16.4.2 Kodieren der Parameter für CGI-Programme  downtop

Wenn aus einer HTML-Datei mit Formularen über Submit Daten an das CGI-Programm übermittelt werden, dann werden diese Daten kodiert. Dies liegt daran, dass viele Zeichen in URL nicht erlaubt sind. Betrachten wir daher folgenden Ausschnitt aus einer Webseite:

<form method="get" action="/cgi-bin/caller.cgi">
<p>Name:
<input type="text" name="name" value="">
<p>E-Mail:
<input type="text" name="email" value="">
<p>
<input type="submit" name="submit" >
</form>

Die Seite besitzt zwei Felder mit den Namen name und email. Dazu kommt noch ein Submit-Button, der, falls aktiviert, die Daten an das CGI-Programm caller.cgi weitergibt. Wenn wir die Felder mit irgendeinem Inhalt füllen und Submit drücken, sehen wir URL häufig in der Adressleiste des Browsers. Dort erscheint, ohne Zeilenumbruch, zum Beispiel:

http://oho.de/cgi-bin/caller.cgi?
name=Ulli+Ullenboom&email=ulliull@ulli.com&submit=Submit

Da in einer URL keine Leerzeichen erlaubt sind, werden sie durch Pluszeichen kodiert. Es gibt noch weitere Zeichen, die kodiert werden, so das Plus- oder das Gleichheitszeichen oder auch das Und-Symbol. Von diesen Zeichen wird die Hex-Repräsentation als ASCII übersandt, aus »Ulli + Radhia« wird dann »Ulli+%2B+Radhia«. Aus dem Leerzeichen wird ein Plus und aus dem Plus wird %2B.

Neben der Textkodierung fällt noch auf, dass in der übermittelten Zeile jeder Feldname und das Feld mit seinem Feldinhalt übermittelt wird. Somit lässt sich leicht der Inhalt eines Felds heraussuchen, denn nach dem Feldnamen ist ein Gleichheitszeichen eingefügt. Das Ende der Inhalte ist durch ein Und-Zeichen gekennzeichnet.

Wollten wir einen String dieser Art zu einer URL zusammenbauen, um etwa eine Anfrage an ein Suchprogramm zu formulieren, dann müssen wir den String nicht kodieren. Dies übernimmt die Java-Klasse URLEncoder.

Abbildung

Listing 16.6   URLEncodeTest.java

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

public class URLEncoderDemo
{
  public static void main( String args[] )
  {
    PrintStream o = System.out;

    o.println(URLEncoder.encode("String mit Leerezeichen"));
    o.println(URLEncoder.encode("String%mit%Prozenten"));
    o.println(URLEncoder.encode("String*mit*Sternen"));
    o.println(URLEncoder.encode("String+hat+ein+Plus"));
    o.println(URLEncoder.encode("String/mit/Slashes"));
    o.println(URLEncoder.encode("String\"mit\"Gänsen"));
    o.println(URLEncoder.encode("String:Doppelpunkten"));
    o.println(URLEncoder.encode("String=ist=alles=gleich"));
    o.println(URLEncoder.encode("String&String&String"));
    o.println(URLEncoder.encode("String.mit.Punkten"));
  }
}

Wir bekommen folgende Ausgabe:

String+mit+Leerezeichen
String%25mit%25Prozenten
String*mit*Sternen
String%2Bhat%2Bein%2BPlus
String%2Fmit%2FSlashes
String%22mit%22G%E4nsen
String%3ADoppelpunkten
String%3Dist%3Dalles%3Dgleich
String%26String%26String
String.mit.Punkten

Galileo Computing

16.4.3 Eine Suchmaschine ansprechen  toptop

Wir wollen nun direkt eine Suchmaschine ansprechen und so das Verhalten eines Anfrageprogramms nachbilden. Unser Programm sammelt dazu alle Suchbegriffe als Parameter auf der Kommandozeile, falls keine Parameter vorhanden sind, wird nach »Teletubbies on Tour« gesucht. Anschließend kodiert die Klasse URLEncoder den Such-String und der Inhalt wird hinter die URL des CGI-Programms gehängt, noch getrennt durch ein Fragezeichen. Dieses wird als Anfrage für die Suchmaschine Google verpackt und weggeschickt. Anschließend wird in einer Schleife die HTML-Datei zeilenweise ausgegeben.

Listing 16.7   GoogleSeeker.java

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

public class GoogleSeeker
{
  public static void main( String args[] ) throws Exception
  {
    String s = "";

    if ( args.length == 0 )
      s = "Teletubbies On Tour";
    else
      for ( int i = 0; i < args.length; i++ )
        s += args[i] + " ";

    s.trim();
    s = "q=" + URLEncoder.encode( s );

    URL u = new URL( "http://www.google.com/search?" + s );

    BufferedReader in = new BufferedReader(
      new InputStreamReader( u.openStream() ) );

    String line, response = null;

    while ( (line = in.readLine()) != null )
      response += line+"\n";

    System.out.print( response );
  }
}




Copyright © Galileo Press GmbH 2003
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de