Hi,
ich versuche grad ein kleines Server-Client-Programm zu schreiben. Hierfür verwende ich beim Server einen ThreadPool, damit evtl. mehrere Clients gleichzeitig mit dem Server interagieren können. Ist das okay, oder sollte man inzwischen lieber NIO verwenden?
Mit dem ThreadPool habe ich jedenfalls das Problem, dass irgendwas scheinbar nicht richtig beendet wird, bzw. im Hintergrund irgendein Thread weiterläuft. Wenn ich nur den Server starte und wieder beende ist alles okay. Wenn ich nur den Client starte bekomme ich "java.net.ConnectException: Connection refused", das ist aber auch richtig so und wenn ich ihn wieder beende scheint auch alles zu funktionieren. Wenn ich alledings erst den Server starte, dann den Client starte und wieder beende und dann auch den Server stoppe, wird in Eclipse das "Terminate"-Symbol rot angezeigt, was ja eigentlich nur der Fall ist, wenn das Programm noch läuft, es scheint also noch irgendwas im Hintergrund zu laufen - oder irre ich mich da?
Mein Code besteht aus 3 Klassen, dem Client, dem Server und dem Handler. Client und Server sollten klar sein, der Handler wird vom Server aufgerufen, sobald ein Client connected und übernimmt in einem seperaten Thread die Kommunikation mit dem Client.
Da das Programm scheinbar nur nicht richtig beendet wird, wenn Server und Client gestartet werden vermute ich, dass das Problem beim Handler liegt. Laut der Ausgabe wird allerdings die while-Schleife beendet. Wo liegt also das Problem?
Server:
Client:
Handler:
Ausgabe:
Server:
Client:
ich versuche grad ein kleines Server-Client-Programm zu schreiben. Hierfür verwende ich beim Server einen ThreadPool, damit evtl. mehrere Clients gleichzeitig mit dem Server interagieren können. Ist das okay, oder sollte man inzwischen lieber NIO verwenden?
Mit dem ThreadPool habe ich jedenfalls das Problem, dass irgendwas scheinbar nicht richtig beendet wird, bzw. im Hintergrund irgendein Thread weiterläuft. Wenn ich nur den Server starte und wieder beende ist alles okay. Wenn ich nur den Client starte bekomme ich "java.net.ConnectException: Connection refused", das ist aber auch richtig so und wenn ich ihn wieder beende scheint auch alles zu funktionieren. Wenn ich alledings erst den Server starte, dann den Client starte und wieder beende und dann auch den Server stoppe, wird in Eclipse das "Terminate"-Symbol rot angezeigt, was ja eigentlich nur der Fall ist, wenn das Programm noch läuft, es scheint also noch irgendwas im Hintergrund zu laufen - oder irre ich mich da?
Mein Code besteht aus 3 Klassen, dem Client, dem Server und dem Handler. Client und Server sollten klar sein, der Handler wird vom Server aufgerufen, sobald ein Client connected und übernimmt in einem seperaten Thread die Kommunikation mit dem Client.
Da das Programm scheinbar nur nicht richtig beendet wird, wenn Server und Client gestartet werden vermute ich, dass das Problem beim Handler liegt. Laut der Ausgabe wird allerdings die while-Schleife beendet. Wo liegt also das Problem?
Server:
Java:
package net;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public abstract class Server implements Runnable {
protected int serverPort;
protected ServerSocket serverSocket;
protected boolean isStopped = false;
protected Thread runningThread;
protected ExecutorService threadPool = Executors.newCachedThreadPool();
public Server(int port) {
serverPort = port;
new Thread(this).start();
}
public void run() {
synchronized (this) {
runningThread = Thread.currentThread();
}
openServerSocket();
while (!isStopped()) {
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.");
return;
}
throw new RuntimeException("Error accepting client connection",
e);
}
onClientConnect(clientSocket);
}
threadPool.shutdown();
System.out.println("Server Stopped.");
}
protected abstract void onClientConnect(Socket clientSocket);
private synchronized boolean isStopped() {
return isStopped;
}
public synchronized void stop() {
isStopped = true;
try {
serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
System.out.println("Socket closed.");
}
private void openServerSocket() {
try {
serverSocket = new ServerSocket(serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port " + serverPort, e);
}
}
}
Client:
Java:
package net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public abstract class Client implements Runnable {
Socket server;
boolean connected = false;
protected BufferedReader in;
protected PrintWriter out;
public void connect(String host, int port) {
server = null;
try {
if (connected) {
disconnect();
}
server = new Socket(host, port);
in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(
server.getOutputStream()));
connected = true;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Connected.");
new Thread(this).start();
}
public void run() {
System.out.println("Connection created.");
while (connected) {
try {
reciveMessage(in.readLine());
}
catch (SocketException e) {
System.out.println("Connection interrupted");
disconnect();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Connection closed.");
}
protected abstract void reciveMessage(String message);
public void disconnect() {
try {
if(connected) {
out.close();
in.close();
server.close();
}
connected = false;
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Disconnected.");
}
public boolean isConnected() {
return connected;
}
public void sendMessage(String message) {
if (connected) {
out.print(message);
} else {
System.err.println("Client is not connected to a Server!");
}
}
}
Handler:
Java:
package net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public abstract class Handler implements Runnable {
protected Socket clientSocket = null;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new OutputStreamWriter(
clientSocket.getOutputStream()));
boolean connected = true;
while (connected) {
String message = in.readLine();
System.out.println("t: " + message);
if(message != null) {
reciveMessage(message);
}
else {
connected = false;
}
}
out.close();
in.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Handler stopped.");
}
protected abstract void reciveMessage(String message);
}
Ausgabe:
Server:
Code:
t: clientmessage
t: null
Handler stopped.
Socket closed.
Server Stopped.
Code:
Connected.
Connection created.
Connection interrupted
Disconnected.
Disconnected.
Connection closed.