diff options
| author | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
|---|---|---|
| committer | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
| commit | 33613a85afc4b1481367fbe92a17ee59c240250b (patch) | |
| tree | 670b842326116b376b505ec2263878912fca97e2 /Master/Reference Architectures and Patterns/hjp5/html/k100294.html | |
| download | Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.gz Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.bz2 | |
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100294.html')
| -rw-r--r-- | Master/Reference Architectures and Patterns/hjp5/html/k100294.html | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100294.html b/Master/Reference Architectures and Patterns/hjp5/html/k100294.html new file mode 100644 index 0000000..5098e52 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100294.html @@ -0,0 +1,824 @@ +<html>
+<head>
+<title>
+Handbuch der Java-Programmierung, 5. Auflage
+</title>
+</head>
+<body>
+<a name="startofbody"></a>
+<script language="JavaScript" src="hjp4lib.js">
+</script>
+<script language="JavaScript">
+installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100292.html;106,k100293.html;107,k100295.html;108,k100298.html");
+</script>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100292.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100293.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100295.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100298.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">Kapitel 46 - Netzwerkprogrammierung
+</table>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel2id046002"></a>
+<h2>46.2 Client-Sockets </h2>
+<hr>
+<ul>
+<li><a href="k100294.html#sectlevel2id046002">46.2 Client-Sockets</a>
+<ul>
+<li><a href="k100294.html#sectlevel3id046002001">46.2.1 Adressierung</a>
+<li><a href="k100294.html#sectlevel3id046002002">46.2.2 Aufbau einer einfachen Socket-Verbindung</a>
+<li><a href="k100294.html#sectlevel3id046002003">46.2.3 Lesen und Schreiben von Daten</a>
+<li><a href="k100294.html#zugriffwebserver">46.2.4 Zugriff auf einen Web-Server</a>
+</ul>
+</ul>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel3id046002001"></a>
+<h3>46.2.1 Adressierung </h3>
+
+<p>
+Zur Adressierung von Rechnern im Netz wird die Klasse <a name="ixa103372"><a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a></a>
+des Pakets <a name="ixa103373"><a href="index_j.html#ixb100194"><font color=#000080><tt>java.net</tt></font></a></a>
+verwendet. Ein <a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a>-Objekt
+enthält sowohl eine IP-Adresse als auch den symbolischen Namen
+des jeweiligen Rechners. Die beiden Bestandteile können mit den
+Methoden <a name="ixa103374"><a href="index_g.html#ixb102519"><font color=#000080><tt>getHostName</tt></font></a></a>
+und <a name="ixa103375"><a href="index_g.html#ixb102520"><font color=#000080><tt>getHostAddress</tt></font></a></a>
+abgefragt werden. Mit Hilfe von <a name="ixa103376"><a href="index_g.html#ixb102521"><font color=#000080><tt>getAddress</tt></font></a></a>
+kann die IP-Adresse auch direkt als <a href="index_b.html#ixb100242"><font color=#000080><tt>byte</tt></font></a>-Array
+mit vier Elementen beschafft werden:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+String getHostName()
+
+String getHostAddress()
+
+byte[] getAddress()
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/net/InetAddress.html" onClick="this.href=getApiDoc('java.net.InetAddress')"><font color="#660066" size=-1>java.net.InetAddress</font></a></td>
+</tr>
+</table>
+
+<p>
+Um ein <a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a>-Objekt
+zu generieren, stehen die beiden statischen Methoden <a name="ixa103377"><a href="index_g.html#ixb102522"><font color=#000080><tt>getByName</tt></font></a></a>
+und <a name="ixa103378"><a href="index_g.html#ixb102523"><font color=#000080><tt>getLocalHost</tt></font></a></a>
+zur Verfügung:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public static InetAddress getByName(String host)
+ throws UnknownHostException
+
+public static InetAddress getLocalHost()
+ throws UnknownHostException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/net/InetAddress.html" onClick="this.href=getApiDoc('java.net.InetAddress')"><font color="#660066" size=-1>java.net.InetAddress</font></a></td>
+</tr>
+</table>
+
+<p>
+<a href="index_g.html#ixb102522"><font color=#000080><tt>getByName</tt></font></a>
+erwartet einen String mit der IP-Adresse oder dem Namen des Hosts
+als Argument, <a href="index_g.html#ixb102523"><font color=#000080><tt>getLocalHost</tt></font></a>
+liefert ein <a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a>-Objekt
+für den eigenen Rechner. Beide Methoden lösen eine Ausnahme
+des Typs <a name="ixa103379"><a href="index_u.html#ixb102524"><font color=#000080><tt>UnknownHostException</tt></font></a></a>
+aus, wenn die Adresse nicht ermittelt werden kann. Das ist insbesondere
+dann der Fall, wenn kein DNS-Server zur Verfügung steht, der
+die gewünschte Namensauflösung erledigen könnte (beispielsweise
+weil die Dial-In-Verbindung zum Provider gerade nicht besteht).
+
+<p>
+Das folgende Listing zeigt ein einfaches Programm, das zu einer IP-Adresse
+den symbolischen Namen des zugehörigen Rechners ermittelt und
+umgekehrt:
+<a name="listingid046001"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4601.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.net.*;
+<font color="#555555">004 </font>
+<font color="#555555">005 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4601
+<font color="#555555">006 </font>{
+<font color="#555555">007 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">008 </font> {
+<font color="#555555">009 </font> <font color="#0000AA">if</font> (args.length != 1) {
+<font color="#555555">010 </font> System.err.println(<font color="#0000FF">"Usage: java Listing4601 <host>"</font>);
+<font color="#555555">011 </font> System.exit(1);
+<font color="#555555">012 </font> }
+<font color="#555555">013 </font> <font color="#0000AA">try</font> {
+<font color="#555555">014 </font> <font color="#00AA00">//Get requested address</font>
+<font color="#555555">015 </font> InetAddress addr = InetAddress.getByName(args[0]);
+<font color="#555555">016 </font> System.out.println(addr.getHostName());
+<font color="#555555">017 </font> System.out.println(addr.getHostAddress());
+<font color="#555555">018 </font> } <font color="#0000AA">catch</font> (UnknownHostException e) {
+<font color="#555555">019 </font> System.err.println(e.toString());
+<font color="#555555">020 </font> System.exit(1);
+<font color="#555555">021 </font> }
+<font color="#555555">022 </font> }
+<font color="#555555">023 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4601.java"><font color="#000055" size=-1>Listing4601.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 46.1: IP-Adressenauflösung</i></p>
+
+<p>
+Wird das Programm mit <font color="#000077"><tt>localhost</tt></font>
+als Argument aufgerufen, ist seine Ausgabe:
+<font color="#333300">
+<pre>
+localhost
+127.0.0.1
+</pre>
+</font>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+<a name="ixa103380"><i>localhost</i></a> ist eine Pseudo-Adresse für
+den eigenen Host. Sie ermöglicht das Testen von Netzwerkanwendungen,
+auch wenn keine wirkliche Netzwerkverbindung besteht (TCP/IP muss
+allerdings korrekt installiert sein). Sollen wirkliche Adressen verarbeitet
+werden, muss natürlich eine Verbindung zum Netz (insbesondere
+zum DNS-Server) aufgebaut werden können.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Die nachfolgende Ausgabe zeigt die Ausgabe des Beispielprogramms,
+wenn es nacheinander mit den Argumenten <font color="#000077"><tt>java.sun.com</tt></font>,
+<font color="#000077"><tt>www.gkrueger.com</tt></font> und <font color="#000077"><tt>www.addison-wesley.de</tt></font>
+aufgerufen wird:
+<font color="#333300">
+<pre>
+java.sun.com
+192.18.97.71
+
+www.gkrueger.com
+213.221.123.45
+
+www.addison-wesley.de
+194.163.213.76
+</pre>
+</font>
+
+
+<!-- Section -->
+<a name="sectlevel3id046002002"></a>
+<h3>46.2.2 Aufbau einer einfachen Socket-Verbindung </h3>
+
+<p>
+Als <a name="ixa103381"><i>Socket</i></a> bezeichnet man eine streambasierte
+Programmierschnittstelle zur Kommunikation zweier Rechner in einem
+TCP/IP-Netz. Sockets wurden Anfang der achtziger Jahre für die
+Programmiersprache C entwickelt und mit Berkeley UNIX 4.1/4.2 allgemein
+eingeführt. Das Übertragen von Daten über eine Socket-Verbindung
+ähnelt dem Zugriff auf eine Datei:
+<ul>
+<li>Zunächst wird eine Verbindung aufgebaut.
+<li>Dann werden Daten gelesen und/oder geschrieben.
+<li>Schließlich wird die Verbindung wieder abgebaut.
+</ul>
+
+<p>
+Während die Socket-Programmierung in C eine etwas mühsame
+Angelegenheit war, ist es in Java recht einfach geworden. Im wesentlichen
+sind dazu die beiden Klassen <a name="ixa103382"><a href="index_s.html#ixb102527"><font color=#000080><tt>Socket</tt></font></a></a>
+und <a name="ixa103383"><a href="index_s.html#ixb102528"><font color=#000080><tt>ServerSocket</tt></font></a></a>
+erforderlich. Sie repräsentieren Sockets aus der Sicht einer
+Client- bzw. Server-Anwendung. Nachfolgend wollen wir uns mit den
+Client-Sockets beschäftigen, die Klasse <a href="index_s.html#ixb102528"><font color=#000080><tt>ServerSocket</tt></font></a>
+wird im nächsten Abschnitt behandelt.
+
+<p>
+Die Klasse <a href="index_s.html#ixb102527"><font color=#000080><tt>Socket</tt></font></a>
+besitzt verschiedene Konstruktoren, mit denen ein neuer Socket erzeugt
+werden kann. Die wichtigsten von ihnen sind:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public Socket(String host, int port)
+ throws UnknownHostException, IOException
+
+public Socket(InetAddress address, int port)
+ throws IOException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/net/Socket.html" onClick="this.href=getApiDoc('java.net.Socket')"><font color="#660066" size=-1>java.net.Socket</font></a></td>
+</tr>
+</table>
+
+<p>
+Beide Konstruktoren erwarten als erstes Argument die Übergabe
+des Hostnamens, zu dem eine Verbindung aufgebaut werden soll. Dieser
+kann entweder als Domainname in Form eines Strings oder als Objekt
+des Typs <a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a>
+übergeben werden. Soll eine Adresse mehrfach verwendet werden,
+ist es besser, die zweite Variante zu verwenden. In diesem Fall kann
+das übergebene <a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a>-Objekt
+wiederverwendet werden, und die Adressauflösung muss nur einmal
+erfolgen. Wenn der Socket nicht geöffnet werden konnte, gibt
+es eine Ausnahme des Typs <a href="index_i.html#ixb100709"><font color=#000080><tt>IOException</tt></font></a>
+bzw. <a href="index_u.html#ixb102524"><font color=#000080><tt>UnknownHostException</tt></font></a>
+(wenn das angegebene Zielsystem nicht angesprochen werden konnte).
+
+<p>
+Der zweite Parameter des Konstruktors ist die Portnummer. Wie in <a href="k100293.html#portsapplikationen">Abschnitt 46.1.4</a>
+erwähnt, dient sie dazu, den Typ des Servers zu bestimmen, mit
+dem eine Verbindung aufgebaut werden soll. Die wichtigsten Standard-Portnummern
+sind in <a href="k100293.html#portnummern">Tabelle 46.2</a> aufgelistet.
+
+<p>
+Nachdem die Socket-Verbindung erfolgreich aufgebaut wurde, kann mit
+den beiden Methoden <a name="ixa103384"><a href="index_g.html#ixb100671"><font color=#000080><tt>getInputStream</tt></font></a></a>
+und <a name="ixa103385"><a href="index_g.html#ixb100672"><font color=#000080><tt>getOutputStream</tt></font></a></a>
+je ein Stream zum Empfangen und Versenden von Daten beschafft werden:
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
+<tr>
+<td valign=top width=100%>
+<font color="#660066">
+<pre>
+public InputStream getInputStream()
+ throws IOException
+
+public OutputStream getOutputStream()
+ throws IOException
+</pre>
+</font>
+</td>
+<td valign=top>
+<a href="../jdkdocs/api/java/net/Socket.html" onClick="this.href=getApiDoc('java.net.Socket')"><font color="#660066" size=-1>java.net.Socket</font></a></td>
+</tr>
+</table>
+
+<p>
+Diese Streams können entweder direkt verwendet oder mit Hilfe
+der Filterstreams in einen bequemer zu verwendenden Streamtyp geschachtelt
+werden. Nach Ende der Kommunikation sollten sowohl die Eingabe- und
+Ausgabestreams als auch der Socket selbst mit <a href="index_c.html#ixb100957"><font color=#000080><tt>close</tt></font></a>
+geschlossen werden.
+
+<p>
+Als erstes Beispiel wollen wir uns ein Programm ansehen, das eine
+Verbindung zum <a name="ixa103386"><i>DayTime</i></a>-Service auf
+Port 13 herstellt. Dieser Service läuft auf fast allen UNIX-Maschinen
+und kann gut zu Testzwecken verwendet werden. Nachdem der Client die
+Verbindung aufgebaut hat, sendet der DayTime-Server einen String mit
+dem aktuellen Datum und der aktuellen Uhrzeit und beendet dann die
+Verbindung.
+<a name="daytimeabfrage"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4602.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.net.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">005 </font>
+<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4602
+<font color="#555555">007 </font>{
+<font color="#555555">008 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">009 </font> {
+<font color="#555555">010 </font> <font color="#0000AA">if</font> (args.length != 1) {
+<font color="#555555">011 </font> System.err.println(<font color="#0000FF">"Usage: java Listing4602 <host>"</font>);
+<font color="#555555">012 </font> System.exit(1);
+<font color="#555555">013 </font> }
+<font color="#555555">014 </font> <font color="#0000AA">try</font> {
+<font color="#555555">015 </font> Socket sock = <font color="#0000AA">new</font> Socket(args[0], 13); <a name="daytimeabfrage.a"></a>
+<font color="#555555">016 </font> InputStream in = sock.getInputStream();
+<font color="#555555">017 </font> <font color="#006699">int</font> len;
+<font color="#555555">018 </font> <font color="#006699">byte</font>[] b = <font color="#0000AA">new</font> <font color="#006699">byte</font>[100];
+<font color="#555555">019 </font> <font color="#0000AA">while</font> ((len = in.read(b)) != -1) {
+<font color="#555555">020 </font> System.out.write(b, 0, len);
+<font color="#555555">021 </font> }
+<font color="#555555">022 </font> in.close();
+<font color="#555555">023 </font> sock.close();
+<font color="#555555">024 </font> } <font color="#0000AA">catch</font> (IOException e) {
+<font color="#555555">025 </font> System.err.println(e.toString());
+<font color="#555555">026 </font> System.exit(1);
+<font color="#555555">027 </font> }
+<font color="#555555">028 </font> }
+<font color="#555555">029 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4602.java"><font color="#000055" size=-1>Listing4602.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 46.2: Abfrage des DayTime-Services</i></p>
+
+<p>
+Das Programm erwartet einen Hostnamen als Argument und gibt diesen
+an den Konstruktor von <a href="index_s.html#ixb102527"><font color=#000080><tt>Socket</tt></font></a>
+weiter, der eine Verbindung zu diesem Host auf Port 13 erzeugt. Nachdem
+der Socket steht, wird der <a href="index_i.html#ixb100642"><font color=#000080><tt>InputStream</tt></font></a>
+beschafft. Das Programm gibt dann so lange die vom Server gesendeten
+Daten aus, bis durch den Rückgabewert -1 angezeigt wird, dass
+keine weiteren Daten gesendet werden. Nun werden der Eingabestream
+und der Socket geschlossen und das Programm beendet. Die Ausgabe des
+Programms ist beispielsweise:
+<font color="#333300">
+<pre>
+Sat Nov 7 22:58:37 1998
+</pre>
+</font>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Um in <a href="k100294.html#daytimeabfrage">Listing 46.2</a> den Socket
+alternativ mit einem <a href="index_i.html#ixb102518"><font color=#000080><tt>InetAddress</tt></font></a>-Objekt
+zu öffnen, wäre <a href="k100294.html#daytimeabfrage.a">Zeile 015</a>
+durch den folgenden Code zu ersetzen:
+<font color="#000077">
+<pre>
+InetAddress addr = InetAddress.getByName(args[0]);
+Socket sock = new Socket(addr, 13);
+</pre>
+</font>
+</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#0099CC">
+<tr>
+<td><font color="#FFFFFF"> Tipp </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel3id046002003"></a>
+<h3>46.2.3 Lesen und Schreiben von Daten </h3>
+
+<p>
+Nachdem wir jetzt wissen, wie man lesend auf einen Socket zugreift,
+wollen wir in diesem Abschnitt auch den schreibenden Zugriff vorstellen.
+Dazu schreiben wir ein Programm, das eine Verbindung zum <a name="ixa103387"><i>ECHO-Service</i></a>
+auf Port 7 herstellt. Das Programm liest so lange die Eingaben des
+Anwenders und sendet sie an den Server, bis das Kommando <font color="#000077"><tt>QUIT</tt></font>
+eingegeben wird. Der Server liest die Daten zeilenweise und sendet
+sie unverändert an unser Programm zurück, von dem sie auf
+dem Bildschirm ausgegeben werden. Um Lese- und Schreibzugriffe zu
+entkoppeln, verwendet das Programm einen separaten Thread, der die
+eingehenden Daten liest und auf dem Bildschirm ausgibt. Dieser läuft
+unabhängig vom Vordergrund-Thread, in dem die Benutzereingaben
+abgefragt und an den Server gesendet werden.
+<a name="schreiblesesocket"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* EchoClient.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.net.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">005 </font>
+<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> EchoClient
+<font color="#555555">007 </font>{
+<font color="#555555">008 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">009 </font> {
+<font color="#555555">010 </font> <font color="#0000AA">if</font> (args.length != 1) {
+<font color="#555555">011 </font> System.err.println(<font color="#0000FF">"Usage: java EchoClient <host>"</font>);
+<font color="#555555">012 </font> System.exit(1);
+<font color="#555555">013 </font> }
+<font color="#555555">014 </font> <font color="#0000AA">try</font> {
+<font color="#555555">015 </font> Socket sock = <font color="#0000AA">new</font> Socket(args[0], 7);
+<font color="#555555">016 </font> InputStream in = sock.getInputStream();
+<font color="#555555">017 </font> OutputStream out = sock.getOutputStream();
+<font color="#555555">018 </font> <font color="#00AA00">//Timeout setzen</font>
+<font color="#555555">019 </font> sock.setSoTimeout(300); <a name="schreiblesesocket.f"></a>
+<font color="#555555">020 </font> <font color="#00AA00">//Ausgabethread erzeugen</font>
+<font color="#555555">021 </font> OutputThread th = <font color="#0000AA">new</font> OutputThread(in);
+<font color="#555555">022 </font> th.start();
+<font color="#555555">023 </font> <font color="#00AA00">//Schleife für Benutzereingaben</font>
+<font color="#555555">024 </font> BufferedReader conin = <font color="#0000AA">new</font> BufferedReader(
+<font color="#555555">025 </font> <font color="#0000AA">new</font> InputStreamReader(System.in));
+<font color="#555555">026 </font> String line = <font color="#0000FF">""</font>;
+<font color="#555555">027 </font> <font color="#0000AA">while</font> (<font color="#006699">true</font>) { <a name="schreiblesesocket.a"></a>
+<font color="#555555">028 </font> <font color="#00AA00">//Eingabezeile lesen</font>
+<font color="#555555">029 </font> line = conin.readLine();
+<font color="#555555">030 </font> <font color="#0000AA">if</font> (line.equalsIgnoreCase(<font color="#0000FF">"QUIT"</font>)) {
+<font color="#555555">031 </font> <font color="#0000AA">break</font>;
+<font color="#555555">032 </font> }
+<font color="#555555">033 </font> <font color="#00AA00">//Eingabezeile an ECHO-Server schicken</font>
+<font color="#555555">034 </font> out.write(line.getBytes());
+<font color="#555555">035 </font> out.write(<font color="#0000FF">'\r'</font>);
+<font color="#555555">036 </font> out.write(<font color="#0000FF">'\n'</font>);
+<font color="#555555">037 </font> <font color="#00AA00">//Ausgabe abwarten</font>
+<font color="#555555">038 </font> th.yield(); <a name="schreiblesesocket.b"></a>
+<font color="#555555">039 </font> }
+<font color="#555555">040 </font> <font color="#00AA00">//Programm beenden</font>
+<font color="#555555">041 </font> System.out.println(<font color="#0000FF">"terminating output thread..."</font>);
+<font color="#555555">042 </font> th.requestStop();
+<font color="#555555">043 </font> th.yield();
+<font color="#555555">044 </font> <font color="#0000AA">try</font> {
+<font color="#555555">045 </font> Thread.sleep(1000);
+<font color="#555555">046 </font> } <font color="#0000AA">catch</font> (InterruptedException e) {
+<font color="#555555">047 </font> }
+<font color="#555555">048 </font> in.close(); <a name="schreiblesesocket.e"></a>
+<font color="#555555">049 </font> out.close();
+<font color="#555555">050 </font> sock.close();
+<font color="#555555">051 </font> } <font color="#0000AA">catch</font> (IOException e) {
+<font color="#555555">052 </font> System.err.println(e.toString());
+<font color="#555555">053 </font> System.exit(1);
+<font color="#555555">054 </font> }
+<font color="#555555">055 </font> }
+<font color="#555555">056 </font>}
+<font color="#555555">057 </font>
+<font color="#555555">058 </font><font color="#0000AA">class</font> OutputThread
+<font color="#555555">059 </font><font color="#0000AA">extends</font> Thread
+<font color="#555555">060 </font>{
+<font color="#555555">061 </font> InputStream in;
+<font color="#555555">062 </font> <font color="#006699">boolean</font> stoprequested;
+<font color="#555555">063 </font>
+<font color="#555555">064 </font> <font color="#0000AA">public</font> OutputThread(InputStream in)
+<font color="#555555">065 </font> {
+<font color="#555555">066 </font> <font color="#006699">super</font>();
+<font color="#555555">067 </font> <font color="#006699">this</font>.in = in;
+<font color="#555555">068 </font> stoprequested = <font color="#006699">false</font>;
+<font color="#555555">069 </font> }
+<font color="#555555">070 </font>
+<font color="#555555">071 </font> <font color="#0000AA">public</font> <font color="#0000AA">synchronized</font> <font color="#006699">void</font> requestStop()
+<font color="#555555">072 </font> {
+<font color="#555555">073 </font> stoprequested = <font color="#006699">true</font>;
+<font color="#555555">074 </font> }
+<font color="#555555">075 </font>
+<font color="#555555">076 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> run()
+<font color="#555555">077 </font> {
+<font color="#555555">078 </font> <font color="#006699">int</font> len;
+<font color="#555555">079 </font> <font color="#006699">byte</font>[] b = <font color="#0000AA">new</font> <font color="#006699">byte</font>[100];
+<font color="#555555">080 </font> <font color="#0000AA">try</font> {
+<font color="#555555">081 </font> <font color="#0000AA">while</font> (!stoprequested) { <a name="schreiblesesocket.c"></a>
+<font color="#555555">082 </font> <font color="#0000AA">try</font> {
+<font color="#555555">083 </font> <font color="#0000AA">if</font> ((len = in.read(b)) == -1) { <a name="schreiblesesocket.d"></a>
+<font color="#555555">084 </font> <font color="#0000AA">break</font>;
+<font color="#555555">085 </font> }
+<font color="#555555">086 </font> System.out.write(b, 0, len);
+<font color="#555555">087 </font> } <font color="#0000AA">catch</font> (InterruptedIOException e) { <a name="schreiblesesocket.g"></a>
+<font color="#555555">088 </font> <font color="#00AA00">//nochmal versuchen</font>
+<font color="#555555">089 </font> }
+<font color="#555555">090 </font> }
+<font color="#555555">091 </font> } <font color="#0000AA">catch</font> (IOException e) {
+<font color="#555555">092 </font> System.err.println(<font color="#0000FF">"OutputThread: "</font> + e.toString());
+<font color="#555555">093 </font> }
+<font color="#555555">094 </font> }
+<font color="#555555">095 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/EchoClient.java"><font color="#000055" size=-1>EchoClient.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 46.3: Lesender und schreibender Zugriff auf einen Socket</i></p>
+
+<p>
+Eine Beispielsession mit dem Programm könnte etwa so aussehen
+(Benutzereingaben sind fettgedruckt):
+<font color="#333300">
+<pre>
+guido_k@pc1:/home/guido_k/nettest > <b>java EchoClient localhost</b>
+<b>hello</b>
+hello
+<b>world</b>
+world
+<b>12345</b>
+12345
+<b>quit</b>
+closing output thread...
+</pre>
+</font>
+
+<p>
+Wie im vorigen Beispiel wird zunächst ein Socket zu dem als Argument
+angegebenen Host geöffnet. Das Programm beschafft dann Ein- und
+Ausgabestreams zum Senden und Empfangen von Daten. Der Aufruf von
+<a name="ixa103388"><a href="index_s.html#ixb102531"><font color=#000080><tt>setSoTimeout</tt></font></a></a>
+gibt die maximale Wartezeit bei einem lesenden Zugriff auf den Socket
+an (300 ms.). Wenn bei einem <a href="index_r.html#ixb100984"><font color=#000080><tt>read</tt></font></a>
+auf den <a href="index_i.html#ixb100642"><font color=#000080><tt>InputStream</tt></font></a>
+nach Ablauf dieser Zeit noch keine Daten empfangen wurden, terminiert
+die Methode mit einer <a name="ixa103389"><a href="index_i.html#ixb102532"><font color=#000080><tt>InterruptedIOException</tt></font></a></a>;
+wir kommen darauf gleich zurück. Nun erzeugt das Programm den
+Lesethread und übergibt ihm den Eingabestream. In der nun folgenden
+Schleife (<a href="k100294.html#schreiblesesocket.a">Zeile 027</a>)
+werden so lange Eingabezeilen gelesen und an den Server gesendet,
+bis der Anwender das Programm mit <font color="#000077"><tt>QUIT</tt></font>
+beendet.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Das Programm wurde auf einer LINUX-Version entwickelt, die noch kein
+präemptives Multithreading unterstützt. Die verschiedenen
+Aufrufe von <a name="ixa103390"><a href="index_y.html#ixb102533"><font color=#000080><tt>yield</tt></font></a></a>
+dienen dazu, die Kontrolle an den Lesethread zu übergeben. Ohne
+diesen Aufruf würde der Lesethread gar nicht zum Zuge kommen
+und das Programm würde keine Daten vom Socket lesen. Auf Systemen,
+die präemptives Multithreading unterstützen, sind diese
+Aufrufe nicht notwendig.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF"> Warnung </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Die Klasse <font color="#000077"><tt>OutputThread</tt></font> implementiert
+den Thread zum Lesen und Ausgeben der Daten. Da die Methode <a href="index_s.html#ixb101115"><font color=#000080><tt>stop</tt></font></a>
+der Klasse <a href="index_t.html#ixb100591"><font color=#000080><tt>Thread</tt></font></a>
+im JDK 1.2 als <a href="index_d.html#ixb100161"><font color=#000080><tt>deprecated</tt></font></a>
+markiert wurde, müssen wir mit Hilfe der Variable <font color="#000077"><tt>stoprequested</tt></font>
+etwas mehr Aufwand treiben, um den Thread beenden zu können.
+<font color="#000077"><tt>stoprequested</tt></font> steht normalerweise
+auf <a href="index_f.html#ixb100234"><font color=#000080><tt>false</tt></font></a>
+und wird beim Beenden des Programms durch Aufruf von <font color="#000077"><tt>requestStop</tt></font>
+auf <a href="index_t.html#ixb100233"><font color=#000080><tt>true</tt></font></a>
+gesetzt. In der Hauptschleife des Threads wird diese Variable periodisch
+abgefragt, um die Schleife bei Bedarf abbrechen zu können (<a href="k100294.html#schreiblesesocket.c">Zeile 081</a>).
+
+<p>
+Problematisch bei dieser Technik ist lediglich, dass der Aufruf von
+<a href="index_r.html#ixb100984"><font color=#000080><tt>read</tt></font></a>
+normalerweise so lange blockiert, bis weitere Zeichen verfügbar
+sind. Steht das Programm also in <a href="k100294.html#schreiblesesocket.d">Zeile 083</a>,
+so hat ein Aufruf <font color="#000077"><tt>requestStop</tt></font>
+zunächst keine Wirkung. Da das Hauptprogramm in <a href="k100294.html#schreiblesesocket.e">Zeile 048</a>
+die Streams und den Socket schließt, würde es zu einer
+<a name="ixa103391"><a href="index_s.html#ixb102534"><font color=#000080><tt>SocketException</tt></font></a></a>
+kommen. Unser Programm verhindert das durch den Aufruf von <a href="index_s.html#ixb102531"><font color=#000080><tt>setSoTimeout</tt></font></a>
+in <a href="k100294.html#schreiblesesocket.f">Zeile 019</a>. Dadurch
+wird ein Aufruf von <a href="index_r.html#ixb100984"><font color=#000080><tt>read</tt></font></a>
+nach spätestens 300 ms. mit einer <a href="index_i.html#ixb102532"><font color=#000080><tt>InterruptedIOException</tt></font></a>
+beendet. Diese Ausnahme wird in <a href="k100294.html#schreiblesesocket.g">Zeile 087</a>
+abgefangen, um anschließend vor dem nächsten Schleifendurchlauf
+die Variable <font color="#000077"><tt>stoprequested</tt></font> erneut
+abzufragen.
+
+<!-- Section -->
+
+<a name="zugriffwebserver"></a>
+<h3>46.2.4 Zugriff auf einen Web-Server </h3>
+
+<p>
+Die Kommunikation mit einem Web-Server erfolgt über das HTTP-Protokoll,
+wie es in den RFCs 1945 und 2068 beschrieben wurde. Ein Web-Server
+läuft normalerweise auf TCP-Port 80 (manchmal läuft er zusätzlich
+auch auf dem UDP-Port 80) und kann wie jeder andere Server über
+einen Client-Socket angesprochen werden. Wir wollen an dieser Stelle
+nicht auf Details eingehen, sondern nur die einfachste und wichtigste
+Anwendung eines Web-Servers zeigen, nämlich das Übertragen
+einer Seite. Ein Web-Server ist in seinen Grundfunktionen ein recht
+einfaches Programm, dessen Hauptaufgabe darin besteht, angeforderte
+Seiten an seine Clients zu versenden. Kompliziert wird er vor allem
+durch die Vielzahl der mittlerweile eingebauten Zusatzfunktionen,
+wie beispielsweise Logging, Server-Scripting, Server-Side-Includes,
+Security- und Tuning-Features usw.
+
+<p>
+Fordert ein Anwender in seinem Web-Browser eine Seite an, so wird
+diese Anfrage vom Browser als <a name="ixa103392"><a href="index_g.html#ixb102535"><font color=#000080><tt>GET</tt></font></a></a>-Transaktion
+an den Server geschickt. Um beispielsweise die Seite <font color="#000077"><tt>http://www.javabuch.de/index.html</tt></font>
+zu laden, wird folgendes Kommando an den Server <font color="#000077"><tt>www.javabuch.de</tt></font>
+gesendet:
+<font color="#000077">
+<pre>
+GET /index.html
+</pre>
+</font>
+
+<p>
+Der erste Teil gibt den Kommandonamen an, dann folgt die gewünschte
+Datei. Die Zeile muss mit einer CRLF-Sequenz abgeschlossen werden,
+ein einfaches '\n' reicht nicht aus. Der Server versucht nun die angegebene
+Datei zu laden und überträgt sie an den Client. Ist der
+Client ein Web-Browser, wird er den darin befindlichen HTML-Code interpretieren
+und auf dem Bildschirm anzeigen. Befinden sich in der Seite Verweise
+auf Images, Applets oder Frames, so fordert der Browser die fehlenden
+Seiten in weiteren GET-Transaktionen von deren Servern ab.
+
+<p>
+Die Struktur des GET-Kommandos wurde mit der Einführung von HTTP
+1.0 etwas erweitert. Zusätzlich werden nun am Ende der Zeile
+eine Versionskennung und wahlweise in den darauffolgenden Zeilen weitere
+Headerzeilen mit Zusatzinformationen mitgeschickt. Nachdem die letzte
+Headerzeile gesendet wurde, folgt eine leere Zeile (also ein alleinstehendes
+CRLF), um das Kommandoende anzuzeigen. HTTP 1.0 ist weit verbreitet,
+und das obige Kommando würde von den meisten Browsern in folgender
+Form gesendet werden (jede der beiden Zeilen muss mit CRLF abgeschlossen
+werden):
+<font color="#000077">
+<pre>
+GET /index.html HTTP/1.0
+
+</pre>
+</font>
+
+<p>
+Wird HTTP/1.0 verwendet, ist auch die Antwort des Servers etwas komplexer.
+Anstatt lediglich den Inhalt der Datei zu senden, liefert der Server
+seinerseits einige Headerzeilen mit Zusatzinformationen, wie beispielsweise
+den Server-Typ, das Datum der letzten Änderung oder den MIME-Typ
+der Datei. Auch hier ist jede Headerzeile mit einem CRLF abgeschlossen,
+und nach der letzten Headerzeile folgt eine Leerzeile. Erst dann beginnt
+der eigentliche Dateiinhalt.
+
+<p>
+Das folgende Programm kann dazu verwendet werden, eine Datei von einem
+Web-Server zu laden. Es wird mit einem Host- und einem Dateinamen
+als Argument aufgerufen und lädt die Seite vom angegebenen Server.
+Das Ergebnis wird (mit allen Headerzeilen) auf dem Bildschirm angezeigt.
+<a name="listingid046004"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4604.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.net.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">005 </font>
+<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4604
+<font color="#555555">007 </font>{
+<font color="#555555">008 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">009 </font> {
+<font color="#555555">010 </font> <font color="#0000AA">if</font> (args.length != 2) {
+<font color="#555555">011 </font> System.err.println(
+<font color="#555555">012 </font> <font color="#0000FF">"Usage: java Listing4604 <host> <file>"</font>
+<font color="#555555">013 </font> );
+<font color="#555555">014 </font> System.exit(1);
+<font color="#555555">015 </font> }
+<font color="#555555">016 </font> <font color="#0000AA">try</font> {
+<font color="#555555">017 </font> Socket sock = <font color="#0000AA">new</font> Socket(args[0], 80);
+<font color="#555555">018 </font> OutputStream out = sock.getOutputStream();
+<font color="#555555">019 </font> InputStream in = sock.getInputStream();
+<font color="#555555">020 </font> <font color="#00AA00">//GET-Kommando senden</font>
+<font color="#555555">021 </font> String s = <font color="#0000FF">"GET "</font> + args[1] + <font color="#0000FF">" HTTP/1.0"</font> + <font color="#0000FF">"\r\n\r\n"</font>;
+<font color="#555555">022 </font> out.write(s.getBytes());
+<font color="#555555">023 </font> <font color="#00AA00">//Ausgabe lesen und anzeigen</font>
+<font color="#555555">024 </font> <font color="#006699">int</font> len;
+<font color="#555555">025 </font> <font color="#006699">byte</font>[] b = <font color="#0000AA">new</font> <font color="#006699">byte</font>[100];
+<font color="#555555">026 </font> <font color="#0000AA">while</font> ((len = in.read(b)) != -1) {
+<font color="#555555">027 </font> System.out.write(b, 0, len);
+<font color="#555555">028 </font> }
+<font color="#555555">029 </font> <font color="#00AA00">//Programm beenden</font>
+<font color="#555555">030 </font> in.close();
+<font color="#555555">031 </font> out.close();
+<font color="#555555">032 </font> sock.close();
+<font color="#555555">033 </font> } <font color="#0000AA">catch</font> (IOException e) {
+<font color="#555555">034 </font> System.err.println(e.toString());
+<font color="#555555">035 </font> System.exit(1);
+<font color="#555555">036 </font> }
+<font color="#555555">037 </font> }
+<font color="#555555">038 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4604.java"><font color="#000055" size=-1>Listing4604.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 46.4: Laden einer Seite von einem Web-Server</i></p>
+
+<p>
+Wird das Programm beispielsweise auf einem SUSE-Linux 5.2 mit frisch
+installiertem <a name="ixa103393"><i>Apache-Server</i></a> mit <font color="#000077"><tt>localhost</tt></font>
+und <font color="#000077"><tt>/index.html</tt></font> als Argument
+aufgerufen, so beginnt seine Ausgabe wie folgt:
+<font color="#333300">
+<pre>
+HTTP/1.1 200 OK
+Date: Sun, 08 Nov 1998 18:26:13 GMT
+Server: Apache/1.2.5 S.u.S.E./5.1
+Last-Modified: Sun, 24 May 1998 00:46:46 GMT
+ETag: "e852-45c-35676df6"
+Content-Length: 1116
+Accept-Ranges: bytes
+Connection: close
+Content-Type: text/html
+
+<HTML>
+<HEAD>
+<TITLE>Apache HTTP Server - Beispielseite</TITLE>
+</HEAD>
+<BODY bgcolor=#ffffff>
+<H1> Der Apache WWW Server </H1> <BR>
+Diese Seite soll nur als Beispiel dienen.
+Die <A HREF="./manual/">Dokumentation zum
+Apache-Server</A> finden Sie hier.
+<P>
+...
+</pre>
+</font>
+<hr>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
+Wesley, Version 5.0.1
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100292.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100293.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100295.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100298.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">© 1998, 2007 Guido Krüger & Thomas
+Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
+</table>
+<a name="endofbody"></a>
+</body>
+</html>
|
