11 Networking
Inhalt
Internetadressierung ·Sockets und Ports ·Client/Server-Programmierung ·Multicasting ·höhere
Netzdienste
Literatur:
Das relevante API Paket ist java.net; für remote method
invocation java.rmi.*. Material und Beispiele zum Thema
findet sich in Kapitel 9 von [Fla97a] sowie
in Kapitel 15 von [Eck98]. Auch der entsprechende
Abschnitt aus dem Tutorial [CW96] ist als
Einstieg brauchbar. Darüberhinaus gibt es noch
[Har97] nur über Netzwerkprogrammierung,
aber ich kenne es selbst nicht. Ein wenig über die verschiedenen
Internetprotokolle habe ich aus [Tan96].
-
IP-Adressen: Adressierungschema des
Internet-Protokolls, momentan (IPv4) 32 Bit
-
in dezimaler Punkt-Schreibweise 134.245.253.7
- DNS-Namen: garfield.informatik.uni-kiel.de
- Spezialadressen, z.B. 127.xx.yy.zz: Loopback,
gut zum Testen
- Port
-
TCP-Schichten Modell
- Transport Layer Service Access Point (ISO-Schicht 4), d.h., dort
stehen Transportschicht-Dienste zur Verfügung
- 16-bit Port Nummer. £ 256: ``wohlbekannte``
Ports65, bis
1024 reserviert.
Beispiel 29 [Adresse]
Mittels statischer
Methoden der Klasse InetAddress kann
man die TCP/IP-DNS-Adreßdienste nutzen. Instanzen von
InetAddress sind IP-Adressen (allerdings hat die Klasse keinen
Konstruktor, verwendet für Sockets, ...).
import java.net.*;
public class NSLookup { // einfache DNS-Anfrage
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: NSLookup machine");
System.exit(0); //
};
InetAddress la = InetAddress.getLocalHost();
InetAddress a = InetAddress.getByName(args[0]);
System.out.println(a);
System.out.println("Lokaler Host: " + la);
};
};
-
Sockets: Endpunkte einer Transportverbindung
- dienen zur Interprozeßkommunikation
- Adressierung der Sockets:
Socket = IP-Adresse × Port-Nummer
|
d.h., Socket = Transportschichtadresse, in Java als Instanzen der Klasse
java.net.Socket
- mehrere Verbindungen über den selben Port/Socket möglich
- zurückgegeben von ServerSocket.accept
- zwei Transportprotokolle:66, beide Ende-zu-Ende-Protokolle, beide
voll-duplex
-
Verbindungsorientiert: TCP
-
fehlergesichert
- reihenfolgegesichert ÞByte strom
- Klasse Socket
- verbindungslos: UDP
-
Datagram-Dienst
- Datagramme als Instanzen von DatagramPacket
- Klasse DatagramSocket
-
Server stellt Dienste zur Verfügung; im OO-Modell:
Methoden
- Klienten fordern Dienste an; im OO-Modell:
Methodenaufruf
Beispiel 30 [Server]
Ein einfacher statischer
Server, der einen Socket
aufmacht und zeilenweise Zeichen liest.
import java.io.*;
import java.net.*;
public class Server {
public static final int PORT = 2000; // Portnummer
public static void main (String[] args) throws IOException {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Started: " + s);
try {
Socket socket = s.accept(); // Beginn der Bereitschaft
try {
System.out.println("Connection accepted:" + socket);
BufferedReader in =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true); // autoflush=on for println
while (true) { // Lesen bis "END"
String str = in.readLine(); // zeilenweises Lesen
if (str.equals("END")) break; // Abbruch
System.out.println("Echoing: " + str); // R"uckkanal
out.println("Echoing: " + str); // Echo -> stdout
}; }
finally {
System.out.println("closing ..");
socket.close();
}}
finally {s.close();}};
};
Beispiel 31 [Client]
Hier der zu dem Server aus Beispiel 30 auf
Folie ?? passende Klient.
import java.net.*;
import java.io.*;
public class SingleClient {
public static void main (String[] args) throws IOException {
InetAddress addr = InetAddress.getByName(null); // null = local host
System.out.println("addr = " + addr);
Socket socket = new Socket (addr, SingleServer.PORT);
try {
System.out.println("socket = " + socket);
BufferedReader in =
new BufferedReader(
new InputStreamReader (socket.getInputStream()));
PrintWriter out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
for (int i = 0; i< 10; i++){
out.println("Hello World" + i);
String str = in.readLine();
System.out.println(str);
};
out.println("END");
} finally {
System.out.println("closing...");
socket.close();
}
};
};
-
in der Regel: ein Server für dynamische Anzahl von
Klienten
- Server aus Beispiel 30 kann nur
einen Klienten gleichzeitig bedienen
- Þ Threads
-
der Multi-Server behält den vereinbarten Port im Auge
- sobald neue Anfrage: Erzeugung (``spawn'') eines neuen
Server-Threads
- Socket als Konstruktor- Parameter
Beispiel 32 [Server]
Hier der entsprechende Code.
import java.io.*;
import java.net.*;
public class MultiServer { // Startet die Unterthreads
public static final int PORT = 2000;
public static void main(String[] args)
throws IOException {
ServerSocket s = new ServerSocket(PORT); // Zum Horchen
System.out.println("Started: " + s);
try {
while (true) { // Soviele wie verlangt
Socket socket = s.accept();
try {
new ServeOne(socket); // socket als Param.
} catch (IOException e) {
socket.close();
};
};
}
finally {s.close();};
};
};
Beispiel 33 [Server]
Hier ein einzelner Serverprozeß. Er bekommt den Socket den
er bedienen soll, als Parameter. Ansonsten analog zum Server aus
Beispiel 30.
import java.io.*;
import java.net.*;
public class ServeOne extends Thread {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public ServeOne (Socket s) throws IOException {
// Socket als Parameter
socket = s;
BufferedReader in = // genau vor vorher
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = // ganau wie vorher
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
start(); // ruft run() auf
};
public void run () { // "Uberschreiben der run-Methode
try {
while (true) { // Loop
String str = in.readLine();
if (str.equals("END")) break;
System.out.println("Echoing: " + str);
out.println(str);
};
System.out.println("closing ..");
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException e) {}
};
};
};
Beispiel 34 [Klienten]
Der Vollständigkeit halber noch das selbe für Klientenseite.
Hier der Prozeß, der alle Klienten erzeugt:
import java.net.*;
import java.io.*;
public class ManyClients {
static final int MAX_THREADS = 4;
public static void main(String[] args)
throws IOException, InterruptedException {
InetAddress addr = InetAddress.getByName(null); //
while (true) {
if (OneClient.threadCount() < MAX_THREADS)
new OneClient(addr);
Thread.currentThread().sleep(1000);
};
};
};
Beispiel 35 [Ein Klient]
Schließlich ein einzelner Klient, der Code ist nicht wesentlich anders
als zuvor:
import java.net.*;
import java.io.*;
public class OneClient extends Thread{
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private static int counter = 0;
private int id = counter++;
private static int threadcount = 0;
public static int threadCount() {
return threadcount;
};
public OneClient(InetAddress addr) {
System.out.println("Neuer Klient @ " + id);
threadcount++;
try {
socket = new Socket(addr, MultiServer.PORT); //stat. Adresse
} catch (IOException e) {}
try {
in =
new BufferedReader(
new InputStreamReader (socket.getInputStream()));
out =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
start(); // starte Thread -> run
} catch (IOException e) {
try {
socket.close();
} catch (IOException e2) {}
};
};
public void run() {
try{
for (int i = 0; i< 25; i++){
out.println("Client" + id + ": " + i );
String str = in.readLine();
System.out.println(str);
};
out.println("END");
} catch (IOException e) {
} finally {
try {
socket.close();
} catch (IOException e) {}
threadcount--;
};
};
};
e
-
funktioniert ähnlich wie ServerSockets nur mit
DatagrammSocket
- basierend auf UDP
- Klasse DatagrammPacket: Instanzen sind, klar,
Datagramme, also UDP-SDUs
- zwei Konstruktoren: zum Empfangen und zum Senden
DatagramPacket(buf, buf.length) // R
DatagramPacket(buf, buf.length, inetAddress, port) // S
- Gesendet werden: Arrays von Bytes (Maximum < 64KByte)
- verbindungsloser Dienst Þkeine Analogie zu
ServerSocket.accept()
- Codefragmente:
- Spezialfall: Multicasting
-
URL: Uniform recource allocator
- eindeutige Adressierung von Netzresourcen (oft
HTML-Seiten oder Code):
- Format von URLs. Die Adresse wird meist als DNS-Name
angegeben. Bei dem Dateipfad steht ein / am Ende für die
Standarddatei index.html.
Bestandteil |
Methoden |
Protokoll/Scheme |
|
getProtocol |
Resource-Adresse |
Host-IP-Adresse |
getHost |
|
Datei (inkl. Pfad) |
getFile |
|
Portnummer (opt.) |
getPort |
|
Referenz (opt.) |
getRef |
- URL's als Java- Objekte. Beispiel:70
String hostname = "www.informatik.uni-kiel.de";
String protocol = "http";
String filename = "/inf/deRoever/SS00/Java/"; // = index.html
URL kursurl = new URL(protocol,
hostname,
filename);
- relative Urls in Java: mittels des überladenen
Url-Konstruktors:
URL (URL baseURL, String relativeURL)
Zum Beispiel:
URL gruppenitem_url = new URL(kursurl, "#gruppen");
URL gruppen_url = new URL(kursurl, "gruppen.html");
- Instanzen von URL sind unveränderliche Objekte,
d.h., es gibt keine Methoden setFile etc.
Protokoll |
Verwendung |
Beispiel |
http |
Hypertext (HTML) |
http://www.informatik.uni-kiel.de/~ms |
ftp |
File transfer |
ftp://ftp.informatik.uni-kiel.de/pub/kiel/ |
file |
lokale Datei |
/home/ms/.plan |
news |
Brett/Artikel |
news:cau.ifi.fragen |
news:AA4534345@news.informatik.uni-kiel.de |
|
gopher |
Gopher |
gopher://gopher.informatik.tu-muenchen.de/ |
mailto |
Email |
mailto:ms@informatik.uni-kiel.de |
telnet |
Einloggen |
telnet://snoopy.informatik.uni-kiel.de:80 |
Table 10: Verschiedene URL's
-
Kommunikation mittels Url: öffnen und
schließen passender Ströme71
-
Methode |
Rückgabetyp |
Nutzen |
openConnection() |
UrlConnection |
zum Lesen und Schreiben von und auf die
UrlConnection. |
openStream() |
InputStream |
erlaubt das direkte Lesen von einem Url, |
- Verbindungen auf Anwendungsschicht über Urls
-
Instanzen von UrlConnection
- Ergebnis von openConnection(), kein
Konstruktor72
- Erlaubt mehr Kontrolle über die Verbindung also die
openStream-Methode eines Url-Objektes
- Lesen und Schreiben möglich, aber default: nur Lesen.
Manipulation mit setDoInput und setDoOutput
- eine Reihe weiterer Methoden, bitte selber nachschlagen
July 4, 2000