5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine...

39
5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web- server zu entwickeln. 5.1 Das Protokoll HTTP HTTP ist ein Protokoll der Anwendungsschicht im TCP/IP- Schichtenmodell und regelt insbesondere , wie ein Webbrowser mit einem Webserver im World Wide Web (WWW) kommuni- ziert HTIP verwendet auf der Transportschicht TCP, Damit ein Webbrowser eine Webseite im \XT\Xf\Xl abrufen kann, muss er sie zunächst adressieren. Ein Uniform Resource Locator (URL) ist eine standardisierte URL Adresse, mit der eine beliebige Ressource (z. B. eine HTML-Seite, ein GIF-Bild, eine PDF-Datei, ein Programm) lokalisiert werden kann. So lokalisiert z: B, ht tp://www hs nied errhe in.de/index. html die Website der Hochschule Niederrhein. Der URL hat im Allgemeinen den folgenden Aufbau: protoco1 :I /hos t[ : port] [! path] [/ f i 1e] [#sect i on] Hierbei sind die eingeklammerten Teile optional. Die Angaben bedeuten: pr ot oco1 Protokollname, hier: http hast Domain-Name oder IP-Adresse des Rechners port Portnummer , unter der der Server läuft; die standard- mäßige Portnummer für einen HTTP-Server ist 80 und muss nicht angegeben werden path Name eines Verzeichnisses auf dem Server; die Anga- be ist relativ zur Wurzel des Webverzeichnisses fi le Name einer Datei in dem spezifizierten Verzeichnis sectlon verweist auf eine bestimmte Stelle innerhalb einer HTML-Seite path und fl le müssen keine reale Datei bezeichnen. Sie können auf der Serverseite als logischer Name zur eindeutigen Bezeich- nung einer Ressource interpretiert werden.

Transcript of 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine...

Page 1: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5 Implementierung eines HTTP-Servers

Ziel dieses Kapitels ist es, eine Einfü hrung in das HypertextTransfer Protocol (HTIP) zu geben und einen einfachen Web­server zu entwickeln.

5.1 Das Protokoll HTTPHTTP ist ein Protokoll der Anwendungsschicht im TCP/IP­Schichtenmodell und regelt insbesondere, wie ein Webbrowsermit einem Webserver im World Wide Web (WWW) kommuni­ziert HTIP verwendet auf der Transportschicht TCP,

Damit ein Webbrowser eine Webseite im \XT\Xf\Xl abrufen kann,muss er sie zunächst adressieren.

Ein Uniform Resource Locator (URL) ist eine standardisierte URLAdresse, mit der eine beliebige Ressource (z. B. eine HTML-Seite,ein GIF-Bild, eine PDF-Datei, ein Programm) lokalisiert werdenkann.

So lokalisiert z: B,

ht tp://www hs nied errhein.de/index. html

die Website der Hochschule Niederrhein.

Der URL hat im Allgemeinen den folgenden Aufbau:

protoco1 :I /hos t[ :port] [! path] [/ f i 1e] [#sect i on]

Hierbei sind die eingeklammerten Teile optional.

Die Angaben bedeuten:

prot oco1 Protokollname, hier: http

hast Domain-Name oder IP-Adresse des Rechners

port Portnummer, unter der der Server läuft; die standard­mäßige Portnummer für einen HTTP-Server ist 80 undmuss nicht angegeben werden

path Name eines Verzeichnisses auf dem Server; die Anga­be ist relativ zur Wurzel des Webverzeichnisses

fi l e Name einer Datei in dem spezifiziertenVerzeichnis

sectlon verweist auf eine bestimmte Stelle innerhalbeiner HTML-Seite

path und fl le müssen keine reale Datei bezeichnen. Sie könnenauf der Serverseite als logischer Name zur eindeutigen Bezeich­nung einer Ressource interpretiert werden.

Page 2: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

166

AblaufeinerllTJP-Transaktion

HTIP istzustandslos

5 Implementierung eines HTTP-Servers

Die Interaktion zwischen HTIP-Client und HTIP-Server für eineAnfrage umfasst die folgenden Schritte,

1. Der Server wartet auf eine eingehende HTIP-Anfrage.

2. Der eIient erzeugt einen URL http:/ t .

3. Der eIient versucht. eine TCP-Verbindung zum Server aufzu­bauen.

4. Der Server akzeptiert den Verbindungswunsch.

5. Der eIient sendet eine Nachricht (HTIP-Anfrage) an denServer und fordert die Ressource mit dem spezifizierten URLan.

6. Der Server verarbeitet die Anfrage (z. B. Ausführung einerDatenbankabfrage und Generierung einer HTML-Seite mitdem Abfrageergebnis).

7. Der Server sendet eine Rückantwort (HTTP-Antwort) an denClient, die die angeforderte Ressource oder eine Fehlermel­dung enthält.

8. Der Client verarbeitet die Antwort.

9. Der eIient und/oder der Server schließen die TCP-Verbin­dung.

Der Server hat keine Kenntnis über vorangegangene Anfragendesselben eIient. Jede Anfrage wird unabhängig von vorherge­henden Anfragen bearbeitet. HTTP ist also ein zustandslosesProtokoll.

Für jede HTIP-Anfrage wird bei HTIP 1.0 in der Regel eineneue TCP-Verbindung aufgebaut. Enthält z. B. eine angeforderteHTML-Seite mehrere Grafiken. so muss jede dieser Grafikenseparat angefordert werden (jeweils mit Verbindungsaufbau und-abbau).

eaa s«,Eine HTTP­

Transaktion

Webbrowser

GET Iprodukte/index.html HTTP/1.1

HTTP

HTIP/1 .1 200 OKConte nt-Type: text/htm I

<htm I> ... </htm I>

.00 •

Webserver

Page 3: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.1 Das Protokoll HTIP

HITP 1.0 ist im RPC 1945 der IETP spezifiziert (siehe http: HTIP 1.0//www.i etf.org/rfc/rfcI945.txt).

Die Version HTTP 1.1 unterstützt so genannte persistente Verbin - HTIP 1.1dungen. Während die TCP-Verbindung steht. können mehrereHTTP-Anfragen über diese Verbindung durchgeführt werden.Die Verbindung kann vom Client oder Server abgebaut werden.

HTTP 1.1 ist im RFC 2616 der IETF spezifiziert (siehe http://www.ietf.org/rfc/rfc2616.txt).

Das folgende Programm zeigt den Inhalt der Nachricht (HTIP­Anfrage). die ein Webbrowser an den Webserver schickt.

167

lmport java.lo FlleNotFoundExceptlon;lmport java.lo FlleOutputStream;lmport java.lo. IOExceptlon;lmport java.lo. InputStream;lmport java.lo.OutputStream;lmport java net.ServerSocket;lmport java net.Socket;lmport java net. SocketTl meoutExceptlon;

public class Reporter (prl vate lnt port;prl vate OutputStream out;prl vate ServerSocket server;

public Repor ter(int port . String file)throws Fi l eNotFoundExcept i on (

this.port ~ port:out ~ new Fi l eOut put St ream(fi le ) :

Runtime.getRuntime().addShutdown Hook(new Thread()public void run() {

try {if (out !~ null )

out. fl usht ):out.close():

}i f (server !~ null)

server. cl ase () ;catch (IOException e )

}}) :

Programm 5.1

Page 4: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

168 5 Implementierung eines HTTP-Servers

public void doWork ()try (

server = new ServerSocket(port);whi le (true) (

Socket cllent = server.accept();client.setSoTimeout(3000);Input St ream in ~ client.get lnputStream();

try {l nt c :while ((c ~ in.read()) !~ -1) (

out.write(c);}catch (SocketTimeoutException e)finally {try {

if (in !~ null)in.close();

if (client !~ null )cl i ent. cl ose();

out.write ('lr');out.write(' In');out. fl ush() ;catch (IOException e)

}catch (IOException e) (System.err.println(e.getMessage());

publ i c static void ma in(String[J args) {if (args.length !~ 2) (

System.err.prlntln("java Reporter <port> <flle>");System.exit(l);

int port ~ Int eger .parsel nt (args[OJ ) ;String f i l e ~ args[ lJ ;try (

new Reporter(port, file).doWork();catch (FileNotFound Exception e)System. err.println(e);

Page 5: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.1 Das Protokoll HTIP

Das Programm protokolliert die empfangenen Daten in einerDatei, deren Name beim Aufruf als Parameter mitgegeben wird.Da das Programm keine HTIP-Antwort schickt. wird die Time­out-Steuerung verwendet, um die Transaktion zu beenden.

Aufruf des Programms, Test

java -cp bin Reporter 50000 log.txt

Anforderung einer fiktiven HTML-Seite im Webbrowser (hier,Firefox 3.5}

http://localhos t:50000/abc/xyz.html

Inhalt der Datei log.txt.

GET labc/xyz.html HTTP/1 .1Host : loca lhost:50000User-Agent: Mo zi l l a/ 5. 0 (Windows: U: Wi ndows NT 6.0: de:Accept: textihtml.application/xhtml+xml.application/xml:Accept-Language: de-de.de:q~0.8.en-us:q~0.5.en:q~0.3

Accept- Encoding: gzip.deflateAccept-Charset: I S O - 88 59 -1 . ut f - 8 : q ~0 . 7 . * : q ~0 . 7

Keep-Ali ve: 300Connectl on: keep-all ve

169

Eine HTTP-Anfrage hat den folgenden Aufbau,

• Kap/zeileSie enthält die HTTP-Methode (im Beispiel GET), den Namender angeforderten Ressource ohne Protokoll und Domain­Namen (im Beispiel Iabcl xyz. htm1) und die verwendete Pro­tokollversion (im Beispiel HTIP/1.l).

• Anfragepararneter (optional)Anfrageparameter liefern dem Server zusätzliche Informa­tionen über den Client und seine Anfrage. Jeder Parameterbenutzt eine eigene Zeile und besteht aus dem Namen, einemDoppelpunkt und dem Wert.

• eine Leerzeile

• Nutzdatenteil Coptional)Hier stehen z. B. die in einem Formular eingetragenen Datenbei Anwendung der HTIP-Methode POST.

Kopfzeile, Anfrageparameter und Leerzeile enden jeweils mitCarriage Return und Linefeed. IrIn.

HTIP-Anfrage

Page 6: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

170 5 Implementierung eines HTTP-Servers

sua s.».Struktur einerHTIP-Anfrage

Me thod e Re s s ourc e Ve rs ion\ r\ n

Name : Wer t \r \n

...\ r\ n

xxxxxxxxxxxxxxxxxxxxxxx

Kopfzeile

} Anfrageparameter

Leerzeile

Nutzdaten

HTIP-Methoden

Im einfachsten Fall reicht eine Anfrage der Form

GET lindex.html HTTP/1 . 0

aus, um bereits von einem Webserver verstanden zu werden.

Die HTTP-Methode spezifiziert die vom Server durchzuführendeAktion.

Wichtige HTIP-Methoden sind,

• GETDiese Methode fordert eine Ressource an.

• POSTDiese Methode überträgt Benutzerdaten an den Server.

• HEAODiese Methode fordert Informationen über die Ressource an;die Ressource selbst wird nicht benötigt.

• PUTDiese Methode wird verwendet, um eine Ressource auf demServer zu erstellen bzw. zu ändern.

• OELETEDiese Methode wird verwendet, um eine Ressource auf demServer zu löschen.

PUT und OELETE werden aus Sicherheitsgründen von den meistenWebservern ignoriert.

Anfrageparameter Anfragepararneter können in beliebiger Reihenfolge angegebenwerden. Groß- und Kleinschreibung wird ignoriert.

Die gebräuchlichsten Anfrageparameter sind (siehe obiges Test­beispiel):

• HastRechnemame und optionale Portnummer des Servers

• Us er-AgentKenndaten über den HTIP-Client

Page 7: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.1 Das Protokoll HTIP

• ConnectlonDieser Parameter wird benutzt, um eine persistente TCP­Verbindung anzufordem bzw. zu schließen.

• Content-LengthLänge der Daten (in Byte) im Nutzdatenteil

• Accept-LanguageDieser Parameter gibt die vom Client bevorzugte Sprache an.Der Server kann dann z. B. eine HTML-Seite, die in mehrerenSprachvarianten vorliegt, in der vom Client gewünschtenSprache senden.

• Accept- EncodlngMit diesem Parameter gibt der Client an, welche Komprimie­rungsalgorithmen er versteht. Der Server kann z. B. große Da­teien komprimieren, um die Übertragungszeit zu minimieren.

• Accept-CharsetDieser Parameter gibt die vom Client bevorzugten Zeichen­sätze an.

• AcceptDieser Parameter gibt die vom Client akzeptierten Medienty­pen an. Die gültigen Parameterwerte sind durch den MIME­Standard definiert.

MIME steht für den Standard Multipurpose Internet Mail MIMEExtension. der ursprünglich für E-Mails entworfen wurde.

MIME-Formatangaben werden von HTIP-Clients und HTIP­Servern benutzt. Clients nutzen sie, um dem Server mitzuteilen,welche Medientypen sie handhaben können. Server nutzen sie,um den Client über den Inhaltstyp der gesendeten Ressource zuinformieren.

Die MIME-Formatangabe besteht aus einer Typ- und einer Sub­typangabe,

typ/subtyp

Der MIME-Standard ist im RFC 1521 der IETF spezifiziert (siehehttp://www .i etf.org/rfc/rfcI521.txt).

171

Typ/Subtyp

text/htrn1

text/piain

t ext/xm1

image/ gi f

image/ jpeg

Beschreibung und üblicheErweiteru ng

HTML-Datei ('.hIm, '.html)

ASCII-Text ('.txt)

XML-Datei ('.xml, '.dtd)

GIF-Bild ('.gil)

JPEG-Bild ('.jpeg, '.jpg)

Beispiele vonMedientypen

Page 8: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

172 5 Implementie rung eines HTTP-Servers

i mage / png

ap>1i cat i 00/ pdf

app1i cati 00/ octet­stream

PNG-Bild ('png)

PDF-Dalei [t.pdf]

Binardaten [t.bin. 'exe)

epojtce t t co/ zt p ZIP-Datei Czip)

Für nicht standardisierte subtypen wird das Präfix x- benutzt, z.B. b ezeichn et auct io/x-wa v Audio-Dateien * .wav.

Daten zum Serversenden

Mit der H1TP -Methcde PO ST können Benutzerdaten zum Servergeschickt werden.

Das folgende Beispiel zeigt ein HTML-Formular, dessen Datendurc h Betätigen des Buttons "Senden" zum Server (hier Pro­gramm 5.1) gesendet werden.

name= "nr " size="5"/>name= "bez" s i ze="3Q "/ >name= "preis " s ize= "l0 "/>

t ype="text "typ e="t ext "t ype="text "

<input<input<input

<htnl >

<heed'< t : t l e>POST</ ti t l e></heact><body><form act i on= "http :// local host: 50000/xxx " meth od= "POST"><pre>Arti kel nummer:Bezei chnung:Prei s:-vpre>Beschrei bung:<brv><t exteree name= "b2schr " co1s="6O " rClills= "5"></textarea ><p/><in put type="submi t " va1 ue="Senden "/><i npu t type="reset " va1 ue="Z urückset zen"/ ></form></body>-vht ml>

H7ML-Code desForm ulars

Bild 5..3:

Ein FormularArtlll:~ l ",,,,,,,,~r : ~'c",,'-cccc~cccccccc---B~r~1Ch'lU"\I : Akku-Handslaubsauge r

15.99

[ Se nde n I[ Zurücksetze n I

Das Programm Reporterprotokollie rt:

Page 9: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.1 Das Protokoll HTIP

POST lxxx HTTP/1.1Host: loca1host:50000

Content Type: appllcation/x-www forrn-urlencodedContent Length: 112

nr~4711&bez~Akku-Handstaubsauger&preis~15.gg&beschr~3+Ze11en.+

Kabe11os.+Wandha1terung.+Fugend%FCse+und+B%FCrste.

Die im Formular eingetragenen Daten werden im URL-codierten URL-codiertesFormat (appli cati on/ x-www-form-urlencoded) übertragen. Format

Die im Formular definierten Variablennamen (im Beispiel: nr,bez, preis, beschr) sind mit den vom Benutzer eingegebenenWerten verknüpft. Variable und Wert werden jeweils durch einGleichheitszeichen voneinander getrennt. Die einzelnen Variab­le/Wert-Paare sind durch das Zeichen & getrennt. Alle Zeichenaußer a-z, A-Z, 0-9, -, * werden zuerst in Bytes nach einemCodierungsschema (z. B. 150-8859-1 oder UTF-8) konvertiert.Jedes Byte wird dann durch ein Prozentzeichen. gefolgt vomHexadezimalwert des Bytes dargestellt. Leerzeichen werdendurch + ersetzt.

Formulare können auch die GET-Methode nutzen, um Daten zuübertragen. Die URL-codierten Daten werden nach einem Frage­zeichen ? an den URL angehängt. 1m HTML-Code des obigenFormulars muss nur POST durch GET ersetzt werden. Die Kopfzeileder HTIP-Anfrage hat dann das folgende Aussehen,

GET Ixxx?nr~4711&bez~Akku-Handstaubsauger&preis~15.gg&beschr~

3+Ze11en.+Kabe11os.+Wandha1terung.+Fugend%FCse+und+B%FCrste.HTTPI1.1

Die so codierte Anfragezeichenkette nach dem Fragezeichen Query Stringwird auch als Query String bezeichnet.

Eine HTTP-Antworthat den folgenden Aufbau, HTIP-Antwort

• Kap/zeileSie besteht aus der Protokollversion, dem Status-Code und ei­ner optionalen Status-Meldung.

• Antwortparameter (optional)Antwortparameter liefern dem Client zusätzliche Infor­mationen über den Server und die Antwort.

• eine Leerzeile

• Nutzdatenteil (optional)Dieser enthält die angeforderte Ressource.

173

Page 10: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

174 5 Implementierung eines HTTP-Servers

sua s.«.Struktur einerHTIP-Antwort

Ve rs ion Code Meldung\ r\ n

Name : Wert \r \n

.. .

\ r\ n

xxxxxxxxxxxxxxxxxxxxxxx

Kopfzeile

} Antwortparameter

Leerzeile

Nutzdaten

100 199

200 299

300 399

400 499

500 599

Beispiele:

Status-Code

Beispiel,

HTTP/l. 1 200 OKDate: Fr i. 19 Feb 2010 11:51:42 GHTServer: Apache/1.3.41 (Oarwin) PH P/ 4.4.9

Content Length: 3205Content Type : text /htrnl

<htrnl> ... </html >

Der Status-Code teilt dem Client mit, wie die gewünschte Aktionvom Server ausgeführt "WUrde.

Die Status-Codes sind wie folgt gruppiert

Informative Meldungen

Die Anfrage war erfolgreich

Die Anfrage "WUrde weitergeleitet

Die Anfrage war fehlerhaft

Server-Fehler

200 OK

400 Bad Request

404 Not Found

500 Internal Server Error

501 Not Irnplernented

Siehe auch:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.htrnl

Page 11: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.2 Ein einfacher File-Server

Gebräuchliche Antwortparameter sind:

• DateAktuelles Datum des Servers zum Zeitpunkt der Beant­wortung der Anfrage

• ServerKenndaten über den HTIP-SelVer

• Content-TypeMIME-Format der Nutzdaten

• Content-LengthLänge der Daten (in Byte) im Nutzdatenteil. Werden Websei­ten dynamisch erzeugt, ist die Länge oft nicht bekannt, wes­halb dieser Parameter dann weggelassen wird.

5.2 Ein einfacher File-Server

Einige Antwort­parameter

175

Das folgende Programm ist ein HTTP-Server, der als einzigen Programm 5.2Dienst nach Verbindungsaufnahme mit einem Client immer die-selbe Datei sendet. Zu diesem Zweck muss er also die HTIP-Anfrage des Client gar nicht auswerten.

Der Server wird mit dem Dateinamen als Parameter aufgerufen.Anhand der Dateiendung wird der passende MIME-Typ festge­legt. Die HTIP-Antwort besteht aus der Kopfzeile mit Status­Code 200. den beiden Antwortparametem Content- Type und Con­tent-Lenqt h, einer Leerzeile und dem Inhalt der Datei.

lmport java.ia BufferedOutputStream;import java.ia BufferedReader;import java.ia File;import java.la Flle InputStream;lmport java.lo.IOExceptlon;lmport j ava. jo . InputSt reamReader ;lmport java.lo.OutputStream;lmport java net.InetAddress;lmport java net.ServerSocket;lmport java net.Socket;

public class SingleFileSer verprlvate lnt port;pri vate File file;pri vate String type;

public SingleFileServer(int port. File file) (this.port ~ port;this.file ~ file;type ~ getMi meType(file);

Page 12: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

176 5 Implementierung eines HTTP-Servers

public void startServer() {try (

ServerSocket server = new ServerSocket(port);

InetAddress addr ~ InetAddress.getLocalHost();System.out.println("SingleFileServer auf"

+ addr. getHostName() + "/" + addr. getHostAddress()+ '"." + port + " gestartet ... ");

whi le (true) (Socket cllent = server.accept();new SingleFileThread(cli ent).start();

}catch (IOException e)System.err.println(e);

private class SingleFileThread extends Thread (prl vate Socket ellent;

public SingleFileThread(Socket client)thls.client = client;

public void run() {try (

BufferedReader in ~ new BufferedReader(new Input St reamReader (cl i ent .get l nput St ream() )) ;

String line;whi 1e ((l i ne ~ in. readLi ne()) !~ null

&& !line.equals("")) (

BufferedOutputStream out ~ new BufferedOutputStream(client.getOutputStream());

String header ~ "HTTP/LO 200 OKlrln"+ "Content-Type; " + type + "IrIn"+ "Content-Length; " + file.length() + "IrInIrIn";

out.write(header.getBytes());writeFile(file. out);

out. fl ush() ;out.close() ;in.close();catch (IOException e)System.err.println(e);

Page 13: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.2 Ein einfacher File-Server

finally {try {

if (el ient !~ null)el ient.elose();

}eateh (IOExeeption e)

pri vate String getMimeType(File file)String filename ~ file.getName();if (filename.endsWith(".html")

11 filename.endsWith(" .htm"))return "textihtml";

else if (filename.endsWith(" .txt")11 filename.endsWith(" .java"))

re turn "textlplaln";else if (filename.endsWith(".gif"))

return "lmage/gl f":else if (filename.endsWith(".jpg"))

return "image/ jpeg";else if (filename.endsWith(" .png"))

return "image/png";else if (filename.endsWith(".pdf"))

return "applieation/pdf";else

return "appl i cat i on/ octet- st ream";

pri vate void writeFile(File file. OutputStream out)throws IOExeeption (

FilelnputStream is ~ new FilelnputStream(file);int c;while ((e ~ iS.read()) !~ -1) (

out. write(e);}is .elose();

publie statie void main(String[] args) {if (args.length !~ 2) (

System.err.println("java SingleFlleServer <port> <file>");

System.exi t (1) ;

177

Page 14: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

178

TCP-MonilOr

Bild 505 ,

Konfiguration

5 Implementierung eines HTIP-Servers

i nt port = Integer .parse l nt Cargs[ O] );File fil e = nee Fi le(a rgs [l] );t f Ufil e.i sFil e()) {

Sys tem.er r . pr i nt l nC "Datei ... + args [l]+ .. . i st ni cht vor handen") :

Sys tem.exl t r1) ;

new Singl eFil eServer( port . f i le ) . star tServer( ) :

Au fruf des Servers:

j ava -ce bin St m lel t leier ve- 50000 s rc /St rcler tl ese-v e-vj eva

Eingabe im Webbrowser:

http : / /localhost :50000/

Im Internet s ind Tools verfügbar, mit denen die Deren. die übere ine TCP-Verbindung gesendet werden, angezeigt werden kön ­nen (sieh e Q uellenangabe am Ende des Buches ). Der TCP­Monitor wird zwischen Clien r und Server platziert . Der Gientverbindet sich mit dem TCP-MonilOf. Dieser le itet die Datenweiter an den Server und protoko lliert di e Ein- un d Ausga be.

http: / /loca lhos t : 80 80/

Browser TCP-Monitor

8080

Creilte a New TCP Monil '" ConneCll on:

l ocal Port: ~IS~"~O~~~~Server Name: 1127.0.0.\

Server Port: 150000

1- - ",

Server

50000

Page 15: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.3 Ein HTIP-Server für SQL-Abfragen

5.3 Ein HTTP-Server für SOL-AbfragenWir stellen zunächst Methoden vor, die eine Zeichenkette in einURL-codiertes Format transformieren bzw. eine so codierte Zei­chenkette wieder decodieren können.

Die Klasse java. net. URL Encoder enthält eine Klassenmethode zur URLEncoder

URL-Codierung einer Zeichenkette.

statlc Strlng encode(Strlng s, String enc)throws Unsupported EncodingException

wandelt Zeichen aus 5 in das URL-codierte Format x-WW'w-form­

ur l encoded um, wobei für die Zeichenkodierung das Codierungs­schema enc zugrunde gelegt wird (z. B. lSO-8859-1 oder UTF-8).

Wird das Codierungsschema enc nicht unterstützt, so löst dieseMethode eine Ausnahme vom Typ

java.io.UnsupportedEncod ingException

(Subklasse von IO Exception) aus.

Die Klasse java. net. URLDecoder dient der Decodierung einer URLDecoder

URL-codierten Zeichenkette.

static String decode(String s. String enc)throws Unsupported EncodlngExceptlon

decodiert eine URL-codierte Zeichenkette, wobei für die Zei­chenkodierung das Codierungsschema enc zugrunde gelegt wird.

Das zu entwickelnde Programm Sql Server ermöglicht es, beliebi- Programm 53ge SQL-Anfragen (Abfragen und Änderungen) an eine Daten-bank über den Webbrowser zu schicken.

Dieser spezielle HTIP-Server

• sendet ein Eingabeformular zur Erfassung des SQL-Befehls anden Webbrowser.

• analysiert den SQL-Befehl und führt ihn über ]DBC aus.

• sendet evtl. SQL-Fehlermeldungen und

• sendet das Abfrageergebnis bzw. Informationen über Daten­bankänderungen an den Webbrowser.

179

Page 16: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

180

SqlSeroer

5 Implementierung eines HTTP-Servers

lmport ja va lo.BufferedReader;lmport ja va lo. Flle InputStream;lmport ja va lo. IO Exceptlon;lmport ja va lo. InputStreamReader;lmport ja va lo.PrlntWrlter;lmport ja va net. InetAddress;lmport ja va net.ServerSocket;lmport ja va net.Socket;lmport ja va net.URL Decoder;lmport java sql .Connectlon;l mport java sql .DrlverManager ;i mpor t java sql.ResultSet ;i mpor t java sql.ResultSetl'etaData;i mpor t java sql .SQL Exception;import java sql.Staterrent;import java sql.Types;lmpor t java utll . Propertles;

public class SqlServer (pri vate static final int WlX_RQ WS ~ 1000;pri vate static final int WlX_L ENGTH ~ 1000;prlvate i nt port;private Properties prop;

public SqlServer(int port)this port ~ port;

public void startServer() {try (

// Properties einlesenprop ~ new Properties();Fi l el nput St re am in ~ new Fi l elnput St ream(

"dbconnect.properties");prop.load(in) ;in.close();

ServerSocket server = new ServerSocket(port);Inet Address addr ~ Inet Addr es s . getLocal Host ( ) ;System. out. pri nt1n( "Sq1Server auf " + addr. getHostName()

+ "/" + addr. getHostAddress () + ":" + port+ " gestartet ... ");

whi le (true) (Socket client = server.accept();new Sql Thread(client. prop).start();

}catch (Exception e) (System.err.println(e);System.exit(l);

Page 17: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.3 Ein HTIP-Server für SQL-Abfragen

pri vate class SqlThread extends Threadprivate Socket client;private Properties prop;private Connection con;private BufferedReader in;private PrintWriter out;

public SqlThread(Socket client, Properties prop) (this.client = client;this,prop ~ prop;

publ ic void run() {try (

// Verbindung zur Datenbank herstellencon = Dri verManager.getConnection(prop

,getProper ty(" ur1"), prcp. get Property( "user". ""),prop,getProperty ("password", ""));

in = new BufferedReader(new Input St reamReader (cl i ent,get lnputStream()));

out ~ new PrintWriter(client,getOutputStream(), true);

// HTTP-Request analysierenString sql ~ readRequest();

// HTML-Formul ar sendensendForrn(sq1);

// SOL-Befehl ausführenif(sql !~null)

execute(sql) ;

in.close t ) ;out,close();catch (Exception e) (System,err,println(e);finally {try {

if (con !~ null)con.cl ose C):

if (cli ent !~ null)cl ient.close();

}catch (Exception e)

181

Page 18: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

182

Die MethodereadRequest

5 Implementierung eines HTTP-Servers

// De r Ouellcode der folgenden Me t hoden ist weiter unten/ / abgedruckt:pri vate String readRequest() throws IOExcept i on ( )pri vate void sendForm (String sql) throws IOExcept i on (pri vate void execute(String sql) throws SOL Exception (

public static voi d main(String [] args)if (args.length !- I ) (

System.err.pr l ntln("java SqlServer <por t>");System.exit (l):

int port - Int eger .parseI nt (args [ O] ) :new SqlServ er(port).startServer():

Datenbankspezifische Angaben (URL der Datenbank, User undPasswort) sind in der Datei dbconnect.properties zusam­mengefasst und werden zu Beginn als Properties eingelesen.

Innerhalb der run-Methode der inneren Klasse SqlThread erfolgtdie Interaktion mit dem Client.

Zunächst wird die Verbindung zur Datenbank hergestellt. DieMethode readRequest analysiert dann die HTIP-Anfrage undliefert den vom Benutzer eingegebenen SQL-Befehl.

Die Rückantwort des Servers enthält eine HTML-Seite, die imoberen Teil ein Formular zur Eingabe eines SQL-Befehls und imunteren Teil das Ergebnis der letzten Anfrage enthält.

Die Methode sendForm sendet das Formular mit dem zuletzt ein­gegebenen SQL-Befehl an den Client zurück

Die Methode execute führt den SQL-Befehl aus und sendet dasErgebnis bzw. eine Fehlermeldung. Damit ist dann die HTML­Seite vollständig erzeugt.

Zu Beginn der Sitzung wird nur ein leeres Formular an denClient geschickt.

pr ivate Str ing readRequest() t hrows IOExcept i on (String line - in.readLine():if (line -- null)

throw new IOExcept i on("Ke i n Input ") :

// SO L-Befehle werden über ein Formular mittels POST// gesendetif (!line.startsWith("POST") )

return null;

Page 19: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.3 Ein HTIP-Server für SQL-Abfragen

// BlS zur Leerzelle lesen und Content Length ermlttelnint 1ength ~ 0;whi1e ((line ~ in.readLine()) !~ null

&& !1i ne .equa 1s ( "" )) (I i ne = line.toLowerCase();i f (1 i ne. startsWi th( "content-l ength"))

1ength ~ Integer.parselnt(line.substring(16));

// Zeichen nach der Leerzeile einlesenint c;StringBui1der sb ~ new StringBui1der();for (int i ~ 0; i < 1ength; i++) {

c ~ in. read () ;if (c ~~ -1)

break;sb.append((char) cl;

// Decodierung der "x-WW'w-form urlencoded" ZeichenString query ~ sb.toString();int i ~ query.indexOf('~');

i f (i < 0)

return null;return URLlJecoder decode ique ry.xubst.ri nqt i + 1), "UTF-8");

Es wird nur die HTIP-Methode POST zugelassen. Somit muss derAnfrageparameter Content-Length vorhanden sein. Die Längewird extrahiert und in eine Zahl vom Typ i nt konvertiert. Zei­chenweise werden nun die Daten des Nutzdatenteils in einenPuffer übertragen. Die Daten nach dem Gleichheitszeichenwerden extrahiert und gemäß UTF-8 decodiert.

private void sendForm(String sq1) throws IOExceptionout.print("HTTP/l.O 200 OKlrln"

+ "Content- Type; textihtm1 IrInIrIn" );out print("<htm1><head><tit1e>SQL</tit1e></head>");out print( "<body>"}:out print("<b>" + prop.getProperty("ur1") + "</b><p/>");out pri nt( "<form method~' PQST' accept-charset~' UTF -8' >") ;out pri nt( "<textarea co15=' 80' rows=' 4' narre=' sq 1 '>"):

if(sq1 !~null)

out. print(sq1);

out print("</textarea><p/>");out pri nt( "<i nput type=' submi t ' val ue=' Senden' ><pi>");out print("</form>");

Die MethodesendForm

183

Page 20: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

184

Die Methodeexecute

5 Implementierung eines HTTP-Servers

i f (sql ~~ null)out. pri nt ("</body></htm1>") ;

out. fl ush() ;

Ist der Parameter sq1 gleich null (d. h. es wurden keine Benut­zerdaten gesendet). so erzeugt diese Methode die kompletteHTIP-Antwort ein HTML-Formular. Andernfalls generiert sie nurden ersten Teil der Antwort: ein Formular mit dem zuletzt ge­sendeten SQL-BefehI. Für die Dateneingabe ist das Codierungs­schema vorgegeben; accept-charset~"UTF-8".

private void execute(String sql) throws SQLExceptiontry (

Statement stmt = con.createStatement();

i f (! stmt. execute (sq1)) (

out.println(stmt.getUpdateCount() + " Zeile(n)");stmt.close();return;

// Ausgabe der Zeilen in Form einer HTML-Tabelle

ResultSet rs ~ stmt.getResultSet();ResultSetMetaData rm ~ rS.getMetaData();int n ~ rm.getColumnCount();String[J align ~ new String[nJ;

out.println("<table bgcolor~'white'

+ "border~'l' cellpadding~'5'>");

// Spaltenüberschriften der Tabelleout.println("<tr>") ;for (int i ~ 1; i <~ r: i++) (

// Zahlen werden rechtsbündig ausgerichtetif (rm.getColumnType(i) ~~ Types.TINYINT

11 rm.getColumnType(i) ~~ Types.SMALLINT11 rm.getColumnType(i) ~~ Types. INTEGER11 rm.getColumnType(i) ~~ Types.BIGINT11 rm. getColumnType (i) ~~ Types. REAL11 rm.getColumnType(i) ~~ Types.FLOAT11 rm.getColumnType(i) ~~ Types.DOUBLE11 rm.getColumnType(i) ~~ Types.NUMERIC1 1 rm. getCo1umnType (i) ~~ Types. DEC lMAl)

align[i 1J ~ "right";

Page 21: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.3 Ein HTIP-Server für SQL-Abfragen

elseal ign[i IJ ~ "left";

out.println("<th aligw'" + align[i IJ + "'>"+ rm.getColumnNalTl2(i) + "</th>");

)out.println("</tr>");

// Tabellenzeilen// Anzahl Zellen und Länge elnes Spaltenwerts slnd// begrenztint count = 0;while (rs.next()) {

if (++count > MAX ROWS)break;

185

out. pri nt 1n( "<tr>");for tint l = 1; l <= n ; l++)

String s ~ rS.getString(i);if (rs.wasNull ()) {

s ~ "[NULL]";else (if (s.length() > MAX_LENGTH) (

s ~ s.substring(Q, MAX LENGTH) + "

)out.println("<td valigw'top' aligw'"

+ allgn[l 1J + "'>" + 5 + "<Ztd>"):)out. pri nt 1n( "</tr>") ;

out. pri nt 1n( "</tab1e>");if (count> MAX_ROWS)

out.println("Es werden maximal + MAX ROWS+ " Zellen angezelQt.");

rs .close();stmt. cl ose () ;catch (SOLException e)out.println(e);finally (out. pri nt 1n( "</body></html>");

" .

Der SQL-Befehl wird ausgeführt (Details zur Handhabung desJDBC-API findet man im Kapitel 2). Das Ergebnis der Datenbank­änderung bzw. Abfrage ergibt den zweiten Teil der Antwort anden Client. Das Abfrageergebnis wird in einer HTML-Tabelle

Page 22: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

186

Bild 5 .6 ,SQL-A bfrage

Hupserver

5 Implementieru ng ein es HITP~Servers

dargestellt. Um die an den Browser ZU ü benragende Datenmen­ge zu begrenzen , werden maximal MAX_RQWS Zeilen und je Spa l­tenw ert einer Zeile maximal M\X_LENGTH Zeichen gesendet.

Iab. Iufo. Ilit t'!- - - I

1 3 . ~ s 7 -:~0998 . 3 1 Did:ms, C!>afb I ~"olas :-'~

1 3-1 ~ 8 . 33()().1 -6 1 Dieb ..., Chafb I~,:i<olars ;"Iddd>y

13-338-06658-: IDid:mo;, C'1Iafb I:-"-oddas ~dId>y

13-538-06982-1 IDidms. Chafb I:-.tdda< :-'Iddd>y

5.4 Ein einfacher WebserverSUfi bietet seit Java SE 6 ein einfaches API zur Entw icklung vonHl'Tl'<Servem. Hierbei han delr es sich um die be iden Paketecom. sun. net. httpserv er und com. sun. net. ht tcserver . sct.

Die abstrakte Klasse com. sun. net .httpserverHt tpSer ver besitztdie statische Methode cr eate, mit der eine konkrete Implemen­tieru ng bereitgestellt wird:

stat t c HttpServer creat e( Ine tSocketAddres s addr, i nt backlo g)t hrows IOExcept i on

j eva. net . InetSocketAddress repräsentiert eine Socke t-Adresse.Der Konstruktor InetSocketAddress ( i nt por- t ) erzeugt einenSock et mit der vorgegebenen Porrnummer. back1og bestimmt diemaximale Länge der Warteschlange (siehe Kapire14 .2).

Methoden der Klasse HttpServer :

abstract HttpCon text createContext (St r i ng path,HttpHandler handl erl

liefert eine Instanz vom Typ com.sun. net. nttose-ver .HttpContext,die eine Verbindung eines Pfads (z. B. ~r) mit einer Instanz vomTyp des Interfaces com.sun. net. httpserver .HttpHandler, die dieHTfP-Anfrage bearbeitet , festlegt.

Pur einen HTfP-5erver können mehrere Kontexte (mit unter­schiedlichen Handlem) eingerichtet werden.

Page 23: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.4 Ein einfacher Webserver

Ein vom Browser übermittelter URL wird auf den so genanntenKontext-Pfad "bestmöglich" abgebildet.

Beispiele,

Kontext 1, 1Kontext 2, 1demol

http 111 oca1host: 500001 wird abgebildet auf Kontext 1http 1Ilocalhost:50000/demo/xyz wird abgebildet auf Kontext 2http 111 oca1host: 50000/webapp wird abgebildet auf Kontext 1

abstract vOld setExecutor( Executor executor)legt das java .uti 1 .concurrent . Executor-Objekt fest. Alle HTIP­Anfragen werden diesem Objekt zur Ausführung übergeben(siehe Kapitel 4.8).

abstract void start()startet den Server .

abstract voi d stop(int delay)stoppt den Server, wobei maximal de1ay Sekunden auf die Been­digung der laufenden Anfragen gewartet wird.

Im Folgenden entwickeln wir mit Hilfe dieses API einen einfa- Programm 5.4ehen Webserver, der nur die HTIP-Methode GET versteht, QueryStrings aber nicht verarbeitet. Das Programm wird mit zwei Pa-rametern aufgerufen:

• Portnummer port und

• Name des so genannten Raot-Verzeichnisses dir.

dir ist die Wurzel des Webverzeichnisses, das alle abrufbarenRessourcen enthält.

187

lmport java.lo. IOExceptlon;lmport java net. InetSocketAddress;lmport java uti l .concurrent. Execut or s ;

lmport com .sun.n et.httpserver. HttpServer;

public class Mini WebServer (public static void main(String[] args) throws IOExcept i on {

if (args.length !- 2) (System.out.println ("java Mini WebServer <port> <root>");System.exi t( 0) :

int port - Int eger .parselnt (args [O] ) :String root - args[ I J:

MiniWebServer

Page 24: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

188

HttpHandler

HttpExchange

5 Implementierung eines HTTP-Servers

f l nal Ht t pSer ver server = Ht t pServer create(new Inet Socket Address (por t ) , 0);

Runtime,getRuntime(),addShutdownHook(new Thread()public void run() (

if (server !- null)server,stop(O);

}System, out, pri nt 1n( "Server gestoppt");

}}) ;

server createContext(" t", new Mi ni HttpHandl er (root ) ) ;server setExecutor( Executors.newCachedThreadPool());ser ver. start();System, out, pri nt 1n( "Server gestartet ",");

Die Klasse Mi ni Ht t pHandl er implementiert HttpH andl er und nutztdiverse Methoden der Klasse HttpExchange,

Ein Handler, der die HTIP-Anfrage bearbeitet, muss das Inter­face cam.sun. net. httpserver . Ht t pHandl e r implementieren.

HttpHandler enthält die Methode;

void handle( HttpExchange exchange) throws IOExcept i on

Die abstrakte Klasse cam. sun. net. httpserver . HttpExchange kapseitHTIP-Anfrage und -Antwort und stellt insbesondere die folgen­den Methoden zur Verfügung;

abstract String getRequestMethod()liefert die Il'FTl'<Methode.

abstract UR I getRequestURI()liefert den Uniform Resource Identifier (UR!) der Anfrage, eineVerallgemeinerung des Uniform Resource Locator (URL),

Die java .net. URI-Methode

String getPath()

liefert den Pfad des URI als Zeichenkette.

abstract Inet Socket Address getRemoteAddress()liefert die Socket-Adresse des Client.

abstract Headers getResponseHeaders()liefert eine Map zur Speicherung der Antwortparameter.

Page 25: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.4 Ein einfacher Webserver

In dieser Map (com.sun. net. httpserver Headers) können mit Hilfeder Methode

void add(Str ing key. String value)

Parameter aufgenommen werden.

abstract vOld sendResponseHeaders(lnt reode,long responseLength) throws IOExcepti on

sendet die Kopfzeile mit dem Status-Code rCode und die Ant­wortparameter. responseLength gibt die Anzahl Bytes der Nutzda­ten an (0 = nicht festgelegt).

abstract OutputStream getResponseBody()liefert den Datenstrom, in den die Nutzdaten geschrieben wer­den.

lmport java.lo Flle;lmport java.lo Flle InputStream;lmport java.lo FlleNotFoundExceptlon;lmport java.lo. IOExceptlon;lmport java.lo.OutputStream;lmport java net. HttpURLConnectlon;import java net.UR I ;lmport java net.URLConnectlon;lmport java text.SlmpleDateFormat;lmport java.utll.Date;

lmport com .sun net httpserver. Headers;lmport com.sun net httpserver. HttpExchange ;lmport com.sun net httpserver. HttpHandler;

public class Min iHttpHandler imp lements Ht t pHandlerprlvate Strlng root;

public Mini HttpHandler(String root) (thls.root = root;

public voi d handle(HttpExchange t) throws IOExcept ion (log(t) ;

String method ~ t.getRequestMethod();if (!method.equals("GET")) (

hand le Error(t Ht t pURLConnect l on HTTP NOT_ IMPL EMENTED."Nur die GET -Methode ist zu1ässi g");

return;

UR I uri ~ t.getRequestURI();Stri ng path ~ uri. get Path();

189

MiniHttpHandler

Page 26: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

190 5 Implementierung eines HTTP-Servers

if (path.ends With ("/"))path ~ path + "index. htrnl":

Strlng fllename = root + path;Fi l e file ~ new Fi l e(f i l enarre ) ;

Fi l el nput St ream fis ~ null;OutputStream os ~ null;try (

fis ~ new Fi l el nput St ream(f i l e) ;

String type ~ URLConnection.getFileNa rreMap().getContentTypeFor(fil enarre);

i f (type ~~ null) (type = "appllcatlon/octet-stream";

Headers headers = t .getResponseHeaders();headers .add ("Content-Type". type);t.sendResponseHeaders (HttpURLConnection HTTP_OK. file

.length()) ;

os ~ t.getResponseBody();byte data[] ~ new byte[ 1024];i nt cnt;while ((cnt ~ fis.read(data)) !~ -1) (

os.write(data. O. cnt);}catch (Fil eNotFoundException e) {handleError(t Ht t pURLConnect lon HTTP NOT_FOUNO. e

.getMessage ());f inally {try {

i f (fis !~ null)fis .close();

if (os !~ null)os. fl ush();os.close();

}catch (I OExcept ion e)

private void 10g(HttpExchange t) (SimpleOateFormat f ~ new SimpleOateFormat(

"dd.MM.yyyy Hh .nm .ss'"):System.out.println("[" + f.format(new Oate()) + " "

+ t.getRermteAddress() + "] " + t.getRequestMethod()+ " " + t ,getRequestURI ());

Page 27: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.4 Ein einfacher Webserver

private void handleError(HttpExchange t. int status.String msg) throws 10Exception (

Headers headers = t.getResponseHeaders();headers. add( "Content-Type". "textihtml");StringBuilder response ~ new StringBuilder();response.append(

"<html><head><tltle>Fehler</tltle></head>");response.append("<hl>HTTP-Status-Code; " + status

+ "</hl>");response.append("<body>" + msg + "</body></html>");t.sendResponseHeaders(status. response.length());OutputStream os ~ t.getResponseBody();os. write (response. toStri ng() .getBytes (" ISO-8859- I")) ;oS.flush();os .close();

Die Methode handle führt die folgenden Schritte zur Bearbeitungeiner HTIP-Anfrage aus.

1. Ausgabe einer Protokollzeile (Datum/Zeit. Adresse. Methode.URL)

2. Ermittlung der HTIP-Methode. Stimmt diese nicht mit GETüberein, wird eine Fehlerseite zurückgesendet,

3. Ermittlung der angefragten Ressource (Datei). Endet der Pfadmit li/li, so wird die Datei lndex.html im entsprechenden Ver­zeichnis angenommen.

4. Öffnen der Datei. Wird diese nicht gefunden. wird eine Feh-lerseite zurückgesendet,

5. Bestimmung des MIME-Typs

6. Setzen des Headers Content- Type

7. Senden der Kopfzeile und der Antwortparameter der HTIP­Antwort

8. Lesen der Datei und Schreiben der Nutzdaten der HTIP­Antwort

Der MIME-Typ der Ressource wird mit der Methode

URLConnect ion. getF i 1eNameMap () .getContentTypeFor (. .. )

ermittelt.

Die abstrakte Klasse java. net. URLConnectl on ist die Superklassederjenigen Klassen, die eine Netzverbindung zu einer durch denURL adressierten Ressource repräsentieren.

191

Page 28: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

192

Programm 55

XMiniWebSeroer

5 Implementierung eines HTTP-Servers

static FileNameMap getFileNameMap()lädt die Tabelle der MIME-Typen aus der Datei lib\content­types.properties im ]RE-Verzeichnis.

Das Interface java .net. Fi 1eNameMap enthält die Methode

String getContentTypeFor(String fileName).

Sie liefert den MIME-Typ zu einem Dateinamen.

java. net. Ht t pURLConnect i on ist Subklasse von URLConnecti on undenthält insbesondere die HTTP-Status-Codes.

5.5 Webseiten dynamisch erzeugenWir erweitern nun den Mini-Webserver aus Kapitel 5.4 um zu­sätzliche Funktionen.

So können dann z. B. Formulare ausgewertet, Daten in einerDatenbank abgespeichert oder abgefragt werden. Zu diesemZweck unterstützt der neue Server auch die POST-Methode.

Die neue Anwendungsfunktionalität zur dynamischen Erzeugungvon HTML-Seiten wird in eigenen Klassen - unabhängig vomWebserver - realisiert. Diese Klassen können nach Bedarf zurLaufzeit des Webservers dynamisch hinzu geladen werden.

Die Klassen des erweiterten Mini-Webservers befinden sich alleim Paket httpserver .

XMl niWebServ e r unterscheidet sich von der Klasse Mi niWebServerinsbesondere dadurch, dass zwei Kontexte erzeugt werden:

// Stat ische Websei tenser ver. createContext(" t", new Mi ni HttpH andler (root ) ) ;

II Dynamlsche Webseltenser ver.createContext("/prog". new XMini Http Handler());

Der Kontextpfad "I" wird zum Abruf statischer Webseiten ver­wendet. Hier wird der Mi ni HttpH andl er aus Kapitel 5.4 zugeord­net. über den Kontextpfad "/prog" werden mit Hilfe vonXMi ni HttpHandle r Methoden zur dynamischen Erzeugung vonWebseiten ausgeführt. Der URL der verarbeitenden Anwendungmuss die folgende Form haben: /prog/Klasse/methode

Page 29: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.5 Webseiten dynamisch erzeugen

Beispiel, /prog/Testitest1

Der Handler sorgt dann dafür, dass die statische Methode test1der Klasse prog.Test aufgerufen wird.

Der Methodenkopf muss wie folgt aussehen,

public static void methode(HttpQuery query. HttpExchange t)throws IOExceptlon

193

package httpserver ; XMiniHttpHandlerlmport java.lo.IOExceptlon;lmport java.lo.InputStream;lmport java.lo.OutputStream;import java.lang.reflect.Method;import java.net.HttpURLConnection;import java.net.URI;lmport java.text.SlmpleDateFormat;lmport java.utll.Date;

lmport com.sun net httpserver.Headers;lmport com.sun net httpserver.HttpExchange;lmport com.sun net httpserver.HttpHandler;

public class XMiniHttpHandler implements HttpHandler (public void handle(HttpExchange t) throws IOException

log(t) ;

String method ~ t.getRequestMethod();URI uri ~ t.getRequestURI();Stri ng path ~ uri. getPath();

int lastSlash ~ path.lastlndexOf("/");String classNarre ~ path.substring(I. lastSlash).replace(

'/'. '.');

String objectMethod ~ path.substring(lastSlash + I);

String q ~ null;if (rrethod.equals("GET"))

q ~ uri .getRawQuery();else if (method.equals("POST"))q ~ getRawQuery(t);else (handleError(t. HttpURLConnection.HTTP_NOT_IMPLEMENTED.

"Nur GET und POST sind zulässig");return ;

HttpQuery query ~ new HttpQuery(q);

Page 30: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

194 5 Implementierung eines HTTP-Servers

try (Cl ass<?> c = Class.forName(className);Class<?>[] types ~ { Ht t pQuery.cl ass .

Ht t pExchange .cl ass };Method m ~ c.getMethod(objectMethod. types);Object[] args ~ { query. t };m.invoke(null. args);catch (Exception e) (System.err.println(e);

privat e String getRawQuery( HttpExchange t)throws IOExcept ion (

Headers headers ~ t.getRequestHeaders();String value ~ headers.getFirst("Content Length");int length;i f (value !~null ) (

length ~ Int eger .parsel nt (val ue) ;else (length ~ - I;

Input St ream in ~ t.getRequest BJdy();l nt c :StringBuilder sb ~ new String Bui lder();for (int i ~ 0; i < length; i++) (

c ~ in. read();if (c ~~-I)

break;sb.append((char) cl;

return sb.toString();

privat e void log(HttpExchange t ) (SimpleOateFormat f ~ new SimpleOateFormat(

"dd.MM.yyyy HH ;rrrn ;ss" ) ;System.out.println ("[" + f.format (new Oate()) + " "

+ t.getRelTDteAddress() + "] " + t.getRequestMethod()+ " " + t ,getRequestURI ());

private void handleError( HttpExchange t. i nt status.String msg) throws IOExcept ion (

Headers headers ~ t.getResponseHeaders();headers .add ("Content-Type". "textihtm1") ;StringBuilder response ~ new StringBuilder();response.append(

"<html><head><tltle>Fehler</tltle></head>");

Page 31: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.5 Webseiten dynamisch erzeugen

response.append ("<h1>HTIP-Status Code: " + status+ "</h1>"):

response.append("<body>" + msg + "</body></html>"):t.sendResponse Headers(status. response.length()):OutputStream os ~ t.getResponseBody():os. write (response. toStr i ng() .getBytes (" ISO-8859-1" ) ) :os .close():

Die Methode handle extrahiert aus dem URL den Klassennamenmit Paketangabe sowie den Methodennamen. Dann wird derQuery-String im Falle der HTIP-Methode GET ermittelt. Hierzuwird die java. net. UR I-Methode getRawCuery benutzt.

public String getRawQuery()liefert den Query-String im URL-codierten Format.

Im Falle der HTIP-Methode POST werden die Nutzdaten derHTTP-Anfrage entnommen. Um die Anzahl Bytes der Nutzdatenzu bestimmen, werden zunächst die Anfrageparameter mit dercom. sun. net. httpserver .HttpExchange-Methode

getRequestHeaders

ermittelt.

abstract Headers getRequestHeaders()

Die com. sun. net. httpserver .Headers-Methode get Fl rst liefert denersten Wert eines evtl. aus mehreren einzelnen Werten beste­henden Anfrageparameters (hier: Content- Length):

String getFirst(String key)

abstract InputSt ream getRequestBody()liefert die Nutzdaten als Eingabedatenstrom im URL-codiertenFormat.

Mit Hilfe der so ermittelten Nutzdaten wird ein Objekt vom TypHt t pOuery erzeugt (Quellcode siehe weiter unten).

Nun wird die Klasse prog.Klasse geladen und die aus dem URLextrahierte Methode über das RefiRction-API bereitgestellt. An­schließend wird die (statische) Methode mit i nvoke aufgernfen.

Die Class-Methode

M2 t hod getMethod(Stri ng name. Cl ass . parameterTypes )throws NoSuchMethodException

195

Page 32: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

196

HttpQuery

5 Implementierung eines HTTP-Servers

liefert ein l'ethod-Objekt. narre ist der Name der gewünschtenpub1i c-Methode, parameterTypes sind die Parametertypen dieserMethode, durch Cl ass-Objekte repräsentiert.

Die Klasse java.1 ang. refl ect. ~thod repräsentiert eine Methode.

Die l'ethod-Methode

Object invoke(Object ob.j , Object. args)throws IllegalAccessExceptlon,java.lang.reflect. InvocationTargetException

ruft die durch dieses l'ethod-Objekt repräsentierte Methode auf.obj ist das Objekt, für das die Methode ausgeführt werden soll,args sind die Argumente für den Methodenaufruf. Bei einfachenDatentypen werden hier die entsprechenden Hüllobjekte einge­setzt. Ist die Methode statisch, so wird obj ignoriert und kannnull sein.

Dieser indirekte Mechanismus zum Laden von Klassen und Auf­ruf von Methoden ermöglicht es, dass die Klasse zum Zeitpunktder Compilierung nicht bekannt sein muss.

Die Klasse HttpOuery enthält Methoden, die Parameterwerte imURL-codierten Format in decodierter Form bereitstellen. ZurDecodierung wird das Codierungsschema UTF-8 verwendet. Zubeachten ist, dass ein Parametername auch mehrfach auftretenkann. Parametername und -wert werden in einer Hashtable ge­speichert. Der Parametername stellt den Schlüssel dar, die evtl,mehrfach auftretenden Parameterwerte zum gleichen Namenwerden in einem Vektor zusammengefasst, der dann als Wertzum Schlüssel in die Hashtable eingetragen wird.

package httpserver;lmport java.lo.UnsupportedEncodlngExceptlon;lmport java.net.URLDecoder;import java. uti 1.Hashtab1e;lmport java.utll.StrlngTokenlzer;lmport java.utll .Vector;

public class HttpOuery (prlvate Hashtable<Strlng, Vector<Strlng» h;

pub1i c HttpOuery(String query) (h = new Hashtable<String, Vector<String»();parseOueryString(query);

public String getParameter(S tring name) (Vector<String> v = h.get(name);if (v ~~ null)

Page 33: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.5 Webseiten dynamisch erzeugen

return null;else

return v.get(O);

public String[] getParameterValues(String name) (Vector<Strlng> v = h.get(name);if(v~~null)

return null;else (

String[] result ~ new String[v size()];v.copylnto(result);return result;

/** Allgemelne Form elnes Query Strlngs:* namel=valuel&name2=value2.* Eln Feldname kann auch mehrfach auftreten.*/

private void parseQueryString(String query) (StrlngTokenizer params = new StringTokenizer(query, "&");

StringTokenizer param;String name, value;

while (params.hasMoreTokens()) (param = new Stri ngTokeni zer(params. nextToken(), "=");

name = param.nextToken();if (param.hasMoreTokens())

value = param.nextToken();else

value "".

if (name !~ null)String dvalue ~ "".try (

dvalue ~ URLl:ecoder.decode(value. "UTF-8");catch (UnsupportedEncodingException e) (

// Prüfen. ob der Name bereits in der Hashtable// vorkommt. Die Werte werden jeweils in einem// Vektor gespeichert.

Vector<String> v = h.get(name);if(v~~null){

v = new Vector<String>();v.add(dvalue);h put(na me. v);

197

Page 34: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

198

posthtml

Test

5 Implementierung eines HTTP-Servers

else (v.add(dvalue);

Die Klasse prog. Test soll die neue Funktionalität demonstrieren.Die Methode testl wertet ein Formular aus.

<html><head><title>Test (POST)</title></head><body>

<form actiow"/prog/Testitest1" method~"POST"

accept-charset~"UTF-8">

Name: <lnput type="text" slze="60" narre="narre"/><p/><lnput type="checkbox" narre="sprache"

value="Java"/>Java<br/><lnput type="checkbox" narre="sprache"

val ue="C++" />C++<br/><input type~"checkbox" narre~"sprache" value~"C#"/>C#<p/>

<lnput type="submlt" value="Senden"/><lnput type=" reset" val ue-" Löschen" />

</form></body></html>

package prog;

import httpserver HttpOuery;

lmport java lo.IOExceptlon;lmport java lO.OutputStream;import java net. HttpURLConnecti on;

lmport com.sun net.httpserver Headers;lmport com.sun net.httpserver HttpExchange;

public class Test (public static void test1(HttpOuery query. HttpExchange t)

throws IOException (Strl ng narre = query. getPararreter( "name");String[] sprachen ~ query.getPararreterVal ues("sprache");

Headers headers = t.getResponseHeaders();headers .add ("Content-Type". "textihtm1") ;

Page 35: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5,5 Webseiten dynamisch erze uge n

Strin[ßuilder resPJnse - new Strin[ßuilder(),response append(

"<html ><head><ti t l e>Test</ti tl e></head><body>") ,resPJnse append("<b>Name </b> " + name + "<p/>" ) ,response eppenoc '<b-Pron-amnerspr-echen </b><br/> "),i f (sprachen 1- null) (

for (int i - 0, i < sprachen ierutn: i ++)response append(sprachen[iJ + "<br v>" ) .

}response append(

"<p>.e hret-.' /index html '>Zurück</a></p>"),response append("</body></html> "),

t sendkesponselieaders (HttpURLConnection HTTP_OK, response1enutncn:

199

Outpu tStream osos wr -t t erresronseos fl usno:os ctoseö:

:\lII:ne: Hugo Mei""

::ll1a\':3"c_"J C#

t getResPJnseBodyO,toString() getBytes( " ISO-8859 1")) ,

Bild5.7-Formularpost btmt

I..Senden I1 Losehen I

.:"'a m..: Hugo ~![Oer

P.".grammi..rspra c~ ..a :J",-a

C,

Die Anwendung der GET-Methode (im Formular ist POST durchI1:T zu ersetze n) führt zu ei nem entsp reche nde n Erg ebnis ,

au s.e,Ergebnis

Page 36: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

200

MyRepotter

5 Implementierung eines HTTP-Servers

5.6 Protokollierung von HTTP-NachrichtenDas Programm MyReport er kann genutzt werden, um die zwi­schen Client und Server ausgetauschten Daten aufzuzeichnen.

Ein Shutdown hook sorgt für das ordnungsgemäße Schließen derLog-Dateien, wenn das Programm mit Strg+C beendet wird.

lmport ja va lo. FlleOutputStream;lmport ja va lo. IO Exceptlon;lmport ja va lo. InputStream;lmport ja va lO.OutputStream;lmport ja va net.ServerSocket;lmport ja va net.Socket;lmport ja va net.Socket Exceptlon;

publ i c class MyReporter ext ends Thread (prlvate statlc OutputStream logRequest;prlvate statlc OutputStream logResponse;prlvate statlc ServerSocket srv;prlvate statlc lnt counter;

prlvat e Input St ream fro mCllent;prl vate OutputStream toServer;

public MyReporter( InputStream fro mClient,OutputStream toServer) (

th is,fromClient ~ fro mClient;thls.toServer = toSer ver;

public void run() {try (

l nt c :logRequest,write(("#" + counter + "lrln"),get Bytes());while ((c ~ fro mClient,read()) !~ - 1) (

logRequest,write(c);toSer ver.wrlte(c) ;

}catch ( IO Exception e)

try (1ogRequest, wri te("1 rlnl rln" ,getBytes()) ;catch ( IO Exception e) (

public static voi d main(String[J args)int port ~ Int eger ,parsel nt (args[OJ ) ;String remoteHost ~ args[ IJ;

Page 37: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.6 Protokollierung von HTIP-Nachrichten

int remotePort ~ Integer parseInt(args[2]);String filel args[3];String file2 ~ args[4];

// ShutdownHook reglstrlerenRuntime.getRuntime().addShutdownHook(new Thread()

public void run() (try (

if (logRequest !~ null)logRequest.flush();logRequest.close();

}if (logResponse !~ null)

logResponse. fl ush();logResponse.close();

}if (srv !~ null)

srv.close();catch (IOException e) (

)}) ;

try (logRequest ~ new FileOutputStream(filel);logResponse ~ new FileOutputStream(file2);srv = new ServerSocket(port);

whi 1e (true) (Socket client ~ srv.accept();InputStream fromClient ~ client.getInputStream();OutputStream toClient ~ client.getOutputStream();

Socket socket = new Socket(remoteHost, remotePort);InputStream fromServer ~ socket.getInputStream();OutputStream toServer ~ socket.getOutputStream();

counter++;

// Welterleltung vom Cllent an den Server(new MyReporter(fromClient. toServer)).start();

// Welterleltung vom Server an den Cllentlnt c;logResponse.wrlte(

("#" + counter + "lrln").getBytes());while ((c ~ fromServer read()) !~ -1) (

logResponse.write(c);toClient.write(c);

}logResponse. write("lrlnlrln" .getBytes());

201

Page 38: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

202

sua s».MyReporterzeichnetHTIP-Anfrage und-Antwort auf

5 Implementierung eines HTTP-Servers

toClient. fl ush();client.close();socket.close();

}catch (SocketException e)catch ( IOException e) (System.err.println(e);

fromcne nt tos ev er

Client MyReporter Server

toClient Port 40000 fromServer Port 50000

Icgpeqc;l ~peopcq o e~ ~

Das Programm kann wie folgt gestartet werden (Kommando ineiner Zeile}

java -cp bln MyReporter <localPort> <remoteHost> <remotePort><logRequest> <logResponse>

Beispiel,

java -cp bin MyReporter 40000 localhost 50000 10gRequest.txtlogResponse .txt

5.7 Aufgaben

1. Entwickeln Sie ein Programm, mit dem Dateien vom Web­server mittels HTTP herunter geladen werden können. Nut­zen Sie hierzu die Socket-Programmierung mit TCP (sieheKapitel 4).

2. Realisieren Sie eine Variante zum Downloadprogramm inAufgabe 1, indem Sie die folgenden Methoden der KlassenURL und URLConnecti on benutzen.

Die Klasse java. net . URL repräsentiert einen Uniform Re­source Locator.

Page 39: 5.1 Das Protokoll HTTP...5 Implementierung eines HTTP-Servers Ziel dieses Kapitels ist es, eine Einführung in das Hypertext Transfer Protocol (HTIP) zu geben und einen einfachen Web

5.7 Aufgaben

URL(String spec) throws MaiformedU RL Exceptionerzeugt ein URL-Objekt aus der Zeichenkette spec. java. net.Ma lformedURL Exception ist von java. i o. IOExcepti on abgelei­tet.

Die URL-MethodeURLConnectlon openConnection() throws IOExcept lonliefert ein java. net. URLConnecti on-Objekt, das eine Verbin­dung zu einer durch den URL adressierten Ressource reprä­sentiert.

URLConnect i on-Methoden:

int getContentLength ()liefert den Wert des Antwortparameters Content Length.

Input St re am getlnputStream() throws IOExcept i onliefert einen Eingabestrom zum Lesen über diese Verbin­dung .

3. Entwickeln Sie für den erweiterten Webserver XMlnl Web­Server aus Kapitel 5.5 eine Klasse Buecherllste, deren Me­thode getTable die zu einem vom Benutzer in einem For­mular eingegebenen Wort Angaben zu denjenigen Büchernaus einer Bücher-Datenbank anzeigt, deren Titel diesesWort enthalten. Die Daten sollen in einer HTML-Tabelledargestellt werden.

Entwickeln Sie eine weitere Methode, die das Ergebnis imXML-Forrnat ausgibt.

4. Entwickeln Sie mit Hilfe der in Aufgabe 2 genannten Me­thoden die Klasse BuecherCl l ent, die die Bücherliste ausAufgabe 3 im XML-Format anfordert und in einer Datei(result.xml) speichert.

Aufrufbeispiel (Kommando in einer Zeile}

java -cp bin BuecherCiient iocaihost 50000prog/ Buecheriiste/getXML?titei~Topkapi result xmi

203