Advanced   Java   Services
Applet CGI Kommunikation
Back Next Up Home

CGI = Common Gateway Interface


Damit ein WebClient (Browser) mit einem Server kommunizieren kann und von dort (HTML-) Dateien holen kann, muß auf dem Serverrechner eine WebServer Software installiert sein. Der am weitesten verbreitete WebServer ist Apache, der in der Regel unter Linux läuft. Für die Kommunikation zwischen Client und WebServer ist eine standardisierte Schnittstelle notwendig, damit verschiedene WebServer, verschiedene Betriebssysteme und verschiedene Browser miteinander kommunizieren können. Diese Schnittstelle richtet der Webserbver ein, wenn er installiert wird, sie heißt CGI. CGI stattet u.a. das Betriebssystem mit zusätzlichen Umgebungsvariablen aus, die vom Client und Server bedient werden.

Einige CGI Umgebungsvariablen


 Name  Wert (Beispiel)  Bedeutung
 CONTENT_TYPE  application/x-www-form-urlencoded  
 CONTENT_LENGTH  43  
 DOCUMENT_ROOT  C:/Apache/Apache2/htdocs  
 GATEWAY_INTERFACE  CGI/1.1  
 HTTP_ACCEPT  text/plein, text/html, image/gif,
image/x-xbitmap, image/jpeg
 
 HTTP_REFERER  http://192.168.77.77/UmgebungPerl.html  
 HTTP_USER_AGENT  Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)  
 QUERY_STRING    
 REMOTE_ADDR  192.168.11.11  
 REQUEST_METHOD  POST  
 SCRIPT_NAME  /cgi-bin/umgebung.pl  
 SERVER_NAME  192.168.77.77  
 SERVER_PORT  80  
 SERVER_PROTOCOL  HTTP/1.1  
 SERVER_SOFTWARE  Apache/2.0.47 (Win32) mod_jk2/2.0.2  


HTML- und cgi-bin Verzeichnis


Des weiteren richtet jeder WebServer u.a. zwei Verzeichnisse für spezielle Dateien ein. Im Verzeichnis /html (oder bei Apache /htdocs) liegen die HTML-Dateien, die ein Browser anfordern kann. Im Verzeichnis /cgi-bin (oder ähnlich) liegen ausführbare Dateien, die der Browser anfordern kann. Dabei kann es sich um Scriptdateien handeln, die in Perl oder PHP geschrieben sind, es kann sich aber auch um compilierte Dateien handeln (diese sind dann meist in C/C++ geschrieben).

Kommunikation mit einer Datei in /cgi-bin


Kennt ein Applet den Namen einer Datei in /cgi-bin, so kann es über die Methode getCodeBase() mit dieser Datei kommunizieren. Über diesen Weg kann ein Applet auch Dateien auf dem Server anlegen oder etwa eine Datenbankverbindung aufbauen. Genauer gesagt, das Applet richtet seine Anfrage an die Anwendung im Verzeichnis cgi-bin und diese Datei unternimmt dann die entsprechenden Schritte. Nicht das Applet hat also die notwendigen Rechte (etwa zum Schreiben einer Datei), sondern die serverseitige Anwendung. Das Applet kann also nur das tun, was die serverseitige Anwendung zuläßt.

Kommunikation mit der GET-Methode


Bei dieser Methode schickt das Applet die aufgenommenen Daten als Anhang an die URL. Das sieht etwa folgendermaßen aus:

www.straub.as/path/fileName.xxx?firstname=Alois+Nikolaus&secondname=Hinterhuber&email=an%40hinterhuber.de

Dabei ist filename.xxx der Name der Datei, mit der das Applet Kontakt aufnehmen will (in diesem Fall in der regel eine Anwendung im Verzeichnis /cgi-bin). Nach einem Fragezeichen kommen dann die Daten in der Form name1=value1&name2=value2. Ein name, value Paar wird durch ein & getrennt. Enthalten die Daten selbst als Trenner reservierte Zeichen wie = oder &, so müssen diese entsprechend umcodiert werden. Auch darf ein URL-Anhang keine Leerzeichen enthalten, diese werden als + codiert. In Java muß man diese Codierung nicht selbst vornehmen, die Klasse URLEncoder hilft einem dabei. Das nötige hierzu kann man im Kapitel Networking unter URLEncoding nachlesen.

Codeskizze für das Versenden von Daten von einem Applet aus

try
{
   // Daten etwa aus einer TextArea abholen
   String data = sendArea.getText();

   // data muß URL-encoded werden
   String encodedData = URLEncoder.encode(data, "UTF-8");

   // Verbindung aufnehmen zu einer Datei write1.pl im Verzeichnis /cgi-bin
   url = new URL("http", getDocumentBase().getHost(), 80, "/cgi-bin/write1.pl?"+ encodedData) ;
}
catch(Exception ex)
{
   // evtl. Fehlermelsung in einer Statuszeile ausgeben
}

Beim Versenden der Daten im Anhang einer URL werden die Daten automatisch mit der GET-Methode übertragen.

Ein PerlScript schreibt die decodierten Daten in eine Datei

#!c:/Perl/bin/Perl.exe
# write1.pl
#
# Einlesen und Wegschreiben von Daten
# daten werden nach data1.txt geschrieben
# datei wird ins Verzeichnis über cgi-bin gespeichert
# das Applet schickt die Daten mit GET und daher URL-encoded

# Übertragungsmethode feststellen
$method = $ENV{REQUEST_METHOD};

if ($method eq "POST")
{
   $anz = $ENV{CONTENT_LENGTH} ;
   read(stdin, $daten, $anz) ;
}
else
{
   $daten =    $ENV{QUERY_STRING} ;
}
#  bei GET ist CONTENT_LENGTH leer


# die name=value paare sind durch & getrennt, deshalb erstmal aufsplitten nach &
@rohdatenarray = split( /&/, $daten);
# jeder eintrag in das array ist ein name=value paar

foreach $item (@rohdatenarray)
{
   ($name, $_) = split(/=/, $item) ; # aufsplitten nach = , $name wird nicht verwendet

   # split füllt $_ nur dann, wenn wirklich ein = vorkommt
   # kommt kein = vor, so wird alles nach $name geschaufelt
   if ($_ eq "")
   {
      $_ = $name ;
   }

   # tr bezieht sich auf $_
   tr/+/ / ;      #in $_ + durch Leerzeichen ersetzen

   # jetzt müssen in $_ noch die Sonderzeichen berichtigt werden
   $_ =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
   push(@datenarray, $_);  #einfügen der $_ in ein neues array
}
#nun liegen in datenarray sämtliche Daten entschlüsselt vor


# Daten decodiert in file schreiben
open(OUT, ">../data1.txt");
print OUT "methode = $method\n";

foreach $item (@datenarray)
{
   print OUT "$item" ;
}
close(OUT);


# decodierte daten als antwort schicken
print "content-type: text/plain\n\n";
print "methode = $method\n";

foreach $item (@datenarray)
{
   print "$item" ;
}



Das Applet nimmt die Antwort entgegen

try
{
   URLConnection conn = url.openConnection();
   // Das URL-Objekt, mit dem die Daten gesendet worden sind, kein neues !
   InputStream inStream = conn.getInputStream() ;
   String text = readFile(inStream); // Einlesen in eigene Methode verlagern
   // Applet gibt text aus
}
catch(Exception ex)
{
   // Ausgabe von Fehlermeldungen
}

Das Einlesen der Daten übernimmt am Besten eine eigene Methode. Wichtig ist, daß im Konstruktor von InputStreamReader UTF-8 als CharacterEncoding angegeben wird. Nur so werden Sonderzeichen korrekt übersetzt.

String readFile(InputStream is)
   throws IOException
{
   java.nio.charset.Charset utf8 = java.nio.charset.Charset.forName("UTF-8") ;
   BufferedReader br = new BufferedReader( new InputStreamReader(is, utf8) );
   StringBuffer text = new StringBuffer();
   String line;
   while ( (line=br.readLine()) !=null )
      text.append( line+"\n");

   return text.toString();
}


Kommunikation mit der POST-Methode






top Back Next Up Home