Advanced
Java
Services
|
Applet CGI Kommunikation |
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
|
| |
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