Moin Community,
ich habe ein großes Problem... Ich habe angefangen, mich mit dem AIO zu beschäftigen und soweit habe ich bei deren Verwendung keine Probleme, doch tritt bei mir ein merkwürdiger Fehler auf: ich habe eine Endlosschleife, wo keine Endlosschleife sein sollte. ???:L
Zu Anfang schrieb ich für meinen Server und Client jeweils völlig eigene Klassen, die das Lesen für einkommende Nachrichten übernehmen sollten und dort klappte natürlich alles einwandfrei. Jetzt habe ich diese Klassen etwas abstrahiert und diese in Oberklassen umgewandelt, da doch diverse Methoden dasselbe getan haben und dies einfacher zu Regeln war und natürlich für den Server und den Client nochmal spezielle Klassen, die von der zusammengefassten Oberklasse erben und erweiterten, doch genau hier beginnt mein Problem, so wie es den Anschein hat...
Jedesmal, wenn eine Nachricht empfangen wird, egal ob Client oder Server, landet dieser im CompletionHandler der Oberklasse in einer Endlosschleife und teilt mir mit (über die Konsole ausgegeben), dass er durchgehend neue Nachrichten empfängt, obwohl ich nachweisen kann, dass der Server oder Client nur eine einzelne Nachricht gesendet haben. ???:L:autsch:
Lesende Oberklasse:
Klasse Reader erbt von AioReaderBase und erweitert diese um unwichtige Methoden, die ich für mein Programm brauche, aber keinen Einfluss auf die Streams oder das Lesen selbst nehmen.
Die Klasse ServerReader übernimmt die spezifische Bearbeitung einkommender Nachrichten.
Übernimmt das Lesen vom Client
Server
Client
Hier ist auch erstmal der Code auf das wesentliche reduziert bzw auch wegkommentiert.
Nun ist mein Problem, dass die read-Methode der spezifischen Reader-Klassen in einer Endlosschleife aufgerufen werden und ich weiß nicht wieso. Diese wird nur aufgerufen, wenn der Client oder Server erfolgreich eine Nachricht erhalten und dann diese nach meinen Vorgaben abarbeiten, aber dies funktioniert nicht wie erwünscht...
Hoffe, ihr könnt mir bei der Lösung meines Problems helfen.
ich habe ein großes Problem... Ich habe angefangen, mich mit dem AIO zu beschäftigen und soweit habe ich bei deren Verwendung keine Probleme, doch tritt bei mir ein merkwürdiger Fehler auf: ich habe eine Endlosschleife, wo keine Endlosschleife sein sollte. ???:L
Zu Anfang schrieb ich für meinen Server und Client jeweils völlig eigene Klassen, die das Lesen für einkommende Nachrichten übernehmen sollten und dort klappte natürlich alles einwandfrei. Jetzt habe ich diese Klassen etwas abstrahiert und diese in Oberklassen umgewandelt, da doch diverse Methoden dasselbe getan haben und dies einfacher zu Regeln war und natürlich für den Server und den Client nochmal spezielle Klassen, die von der zusammengefassten Oberklasse erben und erweiterten, doch genau hier beginnt mein Problem, so wie es den Anschein hat...
Jedesmal, wenn eine Nachricht empfangen wird, egal ob Client oder Server, landet dieser im CompletionHandler der Oberklasse in einer Endlosschleife und teilt mir mit (über die Konsole ausgegeben), dass er durchgehend neue Nachrichten empfängt, obwohl ich nachweisen kann, dass der Server oder Client nur eine einzelne Nachricht gesendet haben. ???:L:autsch:
Lesende Oberklasse:
Java:
public class AioReaderBase implements CompletionHandler<Integer, Object> {
private ByteBuffer readBuffer;
private final AsynchronousSocketChannel socketChannel;
/**
*
*/
protected byte[] messageBytes;
/**
*
* @param socketChannel
* @throws IOException
* @throws InterruptedException
* @throws ExecutionException
*/
public AioReaderBase(AsynchronousSocketChannel socketChannel)
throws IOException, InterruptedException, ExecutionException {
setReadBuffer(ByteBuffer.allocate(10 * 1024));
this.socketChannel = socketChannel;
}
@Override
public void completed(Integer result, Object attachment) {
read();
socketChannel.read(readBuffer, null, this);
}
/**
*
*/
protected void read() {
messageBytes = new byte[readBuffer.remaining()];
readBuffer.get(messageBytes);
}
@Override
public void failed(Throwable exc, Object attachment) {
// ...
}
/**
*
* @return
*/
public AsynchronousSocketChannel getSocketChannel() {
return socketChannel;
}
/**
*
* @return
*/
public ByteBuffer getReadBuffer() {
return readBuffer;
}
/**
* @param readBuffer
* the readBuffer to set
*/
public void setReadBuffer(ByteBuffer readBuffer) {
this.readBuffer = readBuffer;
}
}
Klasse Reader erbt von AioReaderBase und erweitert diese um unwichtige Methoden, die ich für mein Programm brauche, aber keinen Einfluss auf die Streams oder das Lesen selbst nehmen.
Die Klasse ServerReader übernimmt die spezifische Bearbeitung einkommender Nachrichten.
Java:
public class ServerReader extends Reader {
private Server client;
/**
*
* @param socketChannel
* @param server
* @throws InterruptedException
* @throws ExecutionException
* @throws IOException
*/
public ServerReader(AsynchronousSocketChannel socketChannel, Server server)
throws InterruptedException, ExecutionException, IOException {
super(socketChannel);
setServer(server);
}
private void processReading() throws InterruptedException,
ExecutionException {
System.out.println("Lese Nachricht.");
String msg = new String(messageBytes); // Einlesen der Nachricht
}
private void setServer(Server server) {
if (server == null)
throw new IllegalArgumentException("server == null");
this.client = server;
}
/**
*
* @return
*/
protected Server getClientConn() {
return client;
}
@Override
protected void read() {
try {
super.read();
processReading();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
Übernimmt das Lesen vom Client
Java:
public class ClientReader extends Reader {
private final int serializerPort = 4000;
/**
*
* @param socketChannel
* @param user
* @param host
* @throws IOException
* @throws InterruptedException
* @throws ExecutionException
*/
public ClientReader(AsynchronousSocketChannel socketChannel, User user,
String host) throws IOException,
InterruptedException, ExecutionException {
super(socketChannel, user);
}
@Override
protected void read() {
super.read();
String msg = new String(messageBytes);
// Bearbeitung der empfangenen Nachricht
}
}
Server
Java:
public class Server extends AioServerBase {
private static final int serverPort = 3050, readerPort = 4000;
/**
* Erstellt einen AioServer, der die Verbindung zum Server freischaltet und
* die Clients daraufhin registriert.
*
* @throws IOException
* Bei einem IO-Fehler
*/
public Server() throws IOException {
super(serverPort);
}
/**
*
* @param msg
* Zu versendende Nachricht
* @throws InterruptedException
* Fehler beim Schreiben
* @throws ExecutionException
* Fehler beim Schreiben
*/
public void send(String msg) throws InterruptedException,
ExecutionException {
System.out.println("Schicke Nachricht an Client.");
synchronized (database) {
// Senden der Nachricht mit der normalen write-Methode
}
}
@Override
public void completed(AsynchronousSocketChannel result, Object attachment) {
try {
AioReaderBase reader = new ServerReader(result, this);
result.read(reader.getReadBuffer(), null, reader);
client.accept(null, this);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client
Java:
public class Client extends AioClientBase {
private final String host;
public Client(User user, String host, int port)
throws IOException {
super(host, port);
this.host = host;
}
@Override
public void completed(Void result, Object attachment) {
try {
reader = new ClientReader(server, host);
server.read(reader.getReadBuffer(), null, reader);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Object attachment) {
}
}
Hier ist auch erstmal der Code auf das wesentliche reduziert bzw auch wegkommentiert.
Nun ist mein Problem, dass die read-Methode der spezifischen Reader-Klassen in einer Endlosschleife aufgerufen werden und ich weiß nicht wieso. Diese wird nur aufgerufen, wenn der Client oder Server erfolgreich eine Nachricht erhalten und dann diese nach meinen Vorgaben abarbeiten, aber dies funktioniert nicht wie erwünscht...
Hoffe, ihr könnt mir bei der Lösung meines Problems helfen.