http://www.meine-seite.de:8080/kapitel1/index.html
Das Schulnetz beruht ebenso wie das Internet auf der Tatsache, dass Informationen zwischen Rechnern in einem Netzwerk ausgetauscht werden können.
In diesem Abschnitt werden wir den Austausch von Daten zwischen unterschiedlichen Computern durch verschiedene Java-Programme erläutern.
Ein Rechner in einem Netzwerk ist über seine IP-Adresse (IP steht für Internet Protocol) eindeutig auffindbar. Eine solche IP-Adresse hat beispielsweise die Form 192.168.0.2. Auch Rechner im Internet besitzen jeweils eine IP-Adresse, über die sie von außen erreichbar sind.
Für Menschen ist es allerdings schwierig, sich Zahlen als Adressen für Webseiten zu merken. Deshalb gibt es den sogenannten Domain Name Service (im Deutschen häufig übersetzt mit "Namensauflösung"), kurz DNS, der menschenlesbare Adressen in IP-Adressen umwandelt. Im Prinzip funktioniert das ähnlich wie ein Telefonbuch: zu jedem Namen einer Webseite ist die zugehörige IP gespeichert.
Wenn du die IP-Adresse einer Seite herausfinden möchtest, kannst du beispielsweise auf dieser Seite die Webadresse eines Hosts eingeben, woraufhin die zugehörige IP-Nummer dieses Hosts erscheint.
Ist die IP-Adresse eines Rechners erst bekannt, so muss noch die Route herausgefunden werden, über die eine Verbindung zwischen meinem Rechner und dem entfernten Rechner hergestellt werden kann. Mehr Informationen darüber, wie das funktioniert, findest du z. B. hier.
Zusätzlich zur IP-Adresse des Rechners muss man im Normalfall noch den Port angeben. An jedem Port kann ein Server auf eingehende Anfragen warten. Für normale Internetseiten wird normalerweise Port 80 verwendet.
Somit entspricht die IP-Adresse gewissermaßen der Adresse eines Geschäftshauses, der Port der Türe, wo sich eine bestimmter Service befindet.
Um auf eine Webseite zugreifen zu können, muss man die Adresse nach einem gewissen Schema eingeben. Für eine Internetseite sieht diese beispielsweise so aus:
http://www.meine-seite.de:8080/kapitel1/index.html
http
ist das Protokoll, legt also das Austauschformat fest, in dem die angeforderten Informationen ausgetauscht werden.
www.meine-seite.de
ist der Host, auf dem die angeforderte Seite zu finden ist.
8080
ist der Port, der durch einen Doppelpunkt vom Host getrennt ist. Im Falle einer gewöhnlichen Webseite ist der Port 80 und muss nicht gesondert eingegeben werden.
kapitel1/index.html
ist der Pfad zu der von uns angeforderten Seite auf dem Host.
Weitere Beispiele zu URLs findest du hier auf Wikipedia.
Nachdem nun klar sein sollte, wie man Ressourcen im Internet mit einer eindeutigen "Adresse" versieht, betrachten wir im Folgenden die Umsetzung einer Netzwerkverbindung mit Java.
Möchte man sich beispielsweise mit dem Server mit dem Namen www.meine-seite.de
an Port 8080
verbinden, so gelingt dies in Java mittels
Socket socket=new Socket(java.net.InetAddress.getByName("www.meine-seite.de"),8080); BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream())); OutputStream out=socket.getOutputStream();
Java
Die erste Zeile erzeugt einen socket, also einen Kontaktpunkt für unsere Verbindung. Daraus können ein lesender (in
) und ein schreibender Kanal (out
) erstellt werden.
Beachte, dass die Anweisung Als Programmierer muss man sich um nichts weiter kümmern! |
In unserem Fall wurden ein lesender und ein schreibender Kanal erstellt, die folgendermaßen verwendet werden können:
eingabe=in.readLine(); System.out.println(eingabe); out.write(eingabe.getBytes()); out.write('\n');
Java
Zunächst wird eine Nachricht vom Server mittels eingabe=in.readLine()
eingelesen (bis zum Ende einer Zeile) und daraufhin ausgegeben.
Im Anschluss daran wird in diesem Fall der erhaltene Text noch an den Server zurückgesendet und mit einem Zeilenvorschub (\n
) beendet.
Die Verbindung vom Client zum Server kann durch die folgenden Zeilen beendet werden:
in.close(); out.close(); socket.close();
Java
Den gesamten Code des Clients kann man hier einsehen.
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; public class Client { public static void main(String[] args) { String eingabe=""; try{ Socket socket=new Socket(java.net.InetAddress.getByName("localhost"),6000); BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream())); BufferedReader eingabeKonsole=new BufferedReader(new InputStreamReader(System.in)); OutputStream out=socket.getOutputStream(); eingabe=in.readLine(); System.out.println(eingabe); eingabe=eingabeKonsole.readLine(); out.write(eingabe.getBytes()); out.write('\n'); eingabe=in.readLine(); System.out.println(eingabe); System.out.println(""); in.close(); out.close(); socket.close(); System.out.println("Client erfolgreich beendet ..."); } catch (Exception e){ System.out.println("Fehler aufgetreten: "+e.toString()); System.exit(1); } } }
Java
Auch das Erstellen eines Servers gelingt in Java recht einfach: man muss nur angeben, an welchem Port der Server zur Verfügung steht und, sobald eine Verbindungsanfrage hereinkommt, diese bearbeiten:
try { System.out.println("Warte auf Port 6000 auf Clients"); ServerSocket simpleserver = new ServerSocket(6000); while (true) { Socket simplesocket = simpleserver.accept(); (new server_thread(++counter, simplesocket)).start(); } } catch (IOException e) { System.out.println(e.toString()); }
Java
In diesem Beispiel wartet der Server an Port 6000 und sobald eine Anfrage hereinkommt, wird diese akzeptiert mittels simpleserver.accept()
. Man erhält dabei einen Endpunkt der Verbindung den man in diesem Fall an einen neuen Thread weitergibt, damit der Server für die nächste Anfrage sofort wieder zur Verfügung steht.
Auch der Server benötigt für seine Kommunikation einen Kanal zum Lesen und einen weiteren zum Schreiben. Diese bezieht man im Thread mittels
OutputStream out = simplesocket.getOutputStream(); BufferedReader in_socket = new BufferedReader(new InputStreamReader(simplesocket.getInputStream()));
Java
Mit in
werden hereinkommende Nachrichten empfangen, über out
werden Nachrichten nach außen geschickt:
eingabe = in_socket.readLine(); out.write(text.getBytes());
Java
Am Ende müssen alle Kanäle und der Socket wieder geschlossen werden:
out.close(); in_socket.close(); simplesocket.close();
Java
Somit ist die Verbindung getrennt.
Den Code für einen kompletten Server findest du hier.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Inet4Address; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; public class Server { public static void main(String[] args) { int counter = 0; try { System.out.println("IP-Adresse: " + Inet4Address.getLocalHost().getHostAddress()); } catch (UnknownHostException ex) { } try { System.out.println("Warte auf Port 6000 auf Clients"); ServerSocket simpleserver = new ServerSocket(6000); while (true) { Socket simplesocket = simpleserver.accept(); (new server_thread(++counter, simplesocket)).start(); } } catch (IOException e) { System.out.println(e.toString()); } } } class server_thread extends Thread { private byte name; private String text, eingabe; private Socket simplesocket; public server_thread(int name, Socket simplesocket) { this.name = (byte) name; this.simplesocket = simplesocket; } public void run() { try { System.out.println("\nHabe Verbindung zu Client " + name + " hergestellt!"); OutputStream out = simplesocket.getOutputStream(); BufferedReader in_socket = new BufferedReader(new InputStreamReader(simplesocket.getInputStream())); text = "Hallo Client Nr. " + name + ": Gib ein Wort ein\n"; out.write(text.getBytes()); eingabe = in_socket.readLine(); text = "Hallo Client Nr. " + name + ": Dein Wort war " + eingabe + ". Und tschüss!\n"; out.write(text.getBytes()); System.out.println("\nDas Wort von Client " + name + " war " + eingabe); out.close(); in_socket.close(); simplesocket.close(); } catch (IOException e) { System.out.println("Fehler aufgetreten..." + e.toString()); System.exit(1); } System.out.println("\nVerbindung mit Client " + name + " beendet!"); } }
Java
Für das Anfragen und Übertragen von Internet-Ressourcen wird das HTTP-Protokoll verwendet (Hypertext Transfer Protocol), so auch bei der Nutzung des Internets über einen Browser.
So schickt der Client nach der Verbindung mit dem Server diesem die Anfrage
GET kapitel1/index.html HTTP/1.1 Host: www.meine-seite.de
Wenn diese Seite existiert, antwortet der Server beispielsweise mit
HTTP/1.1 200 OK Content-Length: 5 Connection: close Content-Type: text/html Hallo
Der Status-Code 200 bedeutet, dass die angeforderte Ressource gefunden werden konnte und der Server liefert diese mit einigen Zusatzinformationen zurück:
Content-Length
gibt an, wie lang der Rumpf der Nachricht ist (hier das "Hallo").
Connection: close
gibt an, dass nach dieser Übermittlung vom Server die Verbindung beendet wird.
Content-Type: text/html
gibt an, dass der folgende Rumpf der Nachricht als HTML zu interpretieren ist. Diese Information ist wichtig für den Browser zur korrekten Darstellung.
Mehr zum HTTP-Protokoll findest du auf Wikipedia.
Seit dem NSA-Skandal sind immer mehr Seiten dazu übergegangen, das für die Übertragung verschlüsselter Seiten bestehende HTTPS-Protokoll zu nutzen. Somit funktionieren unsere Beispiele nur mit einem immer kleiner werdenden Teil aller Internetseiten. |
Zu diesem Kapitel stehen vier Programme zur Verfügung:
Server.java und Client.java stellen ein einfaches Chat-Programm zur Verfügung: erst den Server starten, dann den Client und der Eingabeaufforderung Folge leisten.
ClientWhile ermöglicht es, TCP-Anfragen an einen Server zu stellen (ähnlich wie telnet). Damit kann man beispielsweise eine Anfrage gemäß dem HTTP-Protokoll an einen Server im Internet stellen und die Antwort des Servers einsehen.
ServerHttp.java enthält einen rudimentären HTTP-Server, basierend auf Server.java. Sobald der Server gestartet ist, kann auf dem selben Rechner im Browser über die Eingabe von localhost:8080
die Rückgabe des Servers betrachtet werden.
Hier kannst du die vollständigen Programme zu diesem Kapitel herunterladen:
Dateiname |
ServerUndClient.zip |
|
Größe in Bytes |
29053 |
|
Einfügezeitpunkt |
21.10.2017, 13:32:19 |
Wahlweise findest du die einzelnen Programme auch auf Github unter https://github.com/menzelths/ClientUndServer zum Analysieren oder Klonen.