Telematik
1 - Labor SS2002
LB
6 TCP-Server am Beispiel von Chat
Server-Sockets
Um
serverseitig Socket-Verbindung zu verwalten steht in Java die Klasse
java.net.ServerSocket
zur Verfügung. Diese Klasse verwaltet die Zuteilung von serverseitigen
Ports auf Client-Anfragen.
Ein
ServerSocket wird mit dem Port angelegt, auf den sich Clients verbinden
können um eine Kommunikation mit dem Server aufzubauen. Das
nachfolgende Beispiel erstellt einen ServerSocket, welcher Verbindungen
auf Port 4444 akzeptiert:
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
Um
nun einen Kommunikationskanal zum Client aufbauen zu können
stellt die Klasse ServerSocket die Methode Socket
accept() zur Verfügung. Diese Methode liefert ein Socket-Objekt
zurück auf welches ein InputStream bzw. OutputStream geöffnet
werden kann (siehe auch LB5).
Über diese Streams kann die Kommunuikation mit dem Client erfolgen:
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
// process data coming from client socket
} catch (IOException e) {
System.out.println("Accept failed: 4444");
}
Diese
Implementierung eines Server-Sockets erlaubt jedoch nur die sequentielle
Verarbeitung von Client-Anfragen. Mehrere gleichzeitige Anfragen können
mit dieser Implementierung nicht verarbeitet werden, dazu sind Threads
notwendig.
Threads
Threads
erlauben die gleichzeitige Ausführung von mehreren Programmabläufen
in Java. Die Verwaltung der Threads erfolgt dabei vom Betriebssystem
selbst, d.h. die Zuteilung von Prozessorzeit auf einen Thread wird
vom Betriebssystem bestimmt. Threads werden in Java über die
Klasse java.lang.Thread
gekapselt.
Die
Logik eines Threads wird in der Methode void
run() gekapselt. Diese Funktionalität wird auch vom
Interface java.lang.Runnable
bereitgestellt. Dieses Interface ermöglicht es, Ablauflogik
in Klassen zu definieren welche nicht von java.lang.Thread erben.
Um ein Runnable Objekt nun in einem Thread ablaufen zu lassen stellt
die Klasse java.lang.Thread
einen Konstrukor mit einem Runnable Parameter bereit. Ein Thread
wird über die Methode void
start() gestartet.
public class ThreadTest {
// inner class for printing test within a thread
class ThreadPrinter implements Runnable {
String name = "ThreadPrinter";
public ThreadPrinter(String name) {
this.name = name;
}
// Method from interface Runnable
// The thread this runnable is in will
// terminate as soon as this method ends.
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println("Thread " + name + " message no. " + i);
}
}
}
public static void main(String[] args) {
Runnable printer1 = new ThreadPrinter("Printer 1");
Runnable printer2 = new ThreadPrinter("Printer 2");
Runnable printer3 = new ThreadPrinter("Printer 3");
Thread thread1 = new Thread(printer1);
Thread thread2 = new Thread(printer2);
Thread thread3 = new Thread(printer3);
// start all threads - they will terminate as soon as
// the runnables quit executing their run method...
thread1.start();
thread2.start();
thread3.start();
}
}
Je
nach Implementierung des Scheduling-Algorithmus des Betriebssystems
werden die Ausgaben der drei Threads in einer Sequenz abgearbeitet
oder durch time-slicing in unterschiedlicher Reihenfolge aufgerufen.
Bei
der Implementierung von Server-Sockets können Threads vor allem
dazu verwendet werden, mehrere Client-Anfragen gleichzeitig zu bearbeiten
und somit die Rechenleistung des Server-Systems auf mehrere Clients
aufzuteilen. Die Verwendung einers ServerSockets könnte daher
wie folgt aussehen:
// this functionality might itself be implemented in a thread
try {
Socket clientSocket = null;
ServerSocket serverSocket = new ServerSocket(4444);
Thread thread = null;
// instead of "true" there should be some abort condition set
while (true) {
clientSocket = serverSocket.accept();
// spin off a separate Thread - implementation
// is not shown here
thread = new CustomSocketThread(clientSocket);
thread.start();
}
} catch (IOException e) {
System.out.println(e.printStackTrace());
}
Aufgabenstellung
Implementieren
Sie zu dem Chat-Client aus Übung 5 ein entsprechendes Server-Pendant.
|