Ich übe mit NIO und versuche, eine einfache App mit Client-und Server-Seiten zu machen. Diese App sollte nur Nachricht in Bytes von Client an Server senden und andere Nachricht als Antwort erhalten. Mein Code ist hier unten. Aber ich habe viele verschiedene Probleme.Viele Probleme beim Lesen und Schreiben in NIO
Manchmal Zeilen int bytesRead = socketChannel.read(byteBuffer);
oder bytesRead = socketChannel.read(byteBuffer);
von Methode readMessage()
liest endlose Sequenz von Null Bytes und löst OOM-Fehler.
Manchmal reagiert die Antwort vom Server wie that anstelle von {"class":"server.PasswordHashResponse","xoredHash":"RV5GX1JVAwADBEVZWwFGTAhZQ1FGX1tYQ11ZVwA\u003d"}
.
Manchmal hat Antwort ungerade Schwanz wie folgt aus: {"class":"server.PasswordHashResponse","xoredHash":"RV5GX1JVAwADBEVZWwFGTAhZQ1FGX1tYQ11ZVwA\u003d"}YQ11ZVwA\u003d
Beide Server und cliend Verwendung derselben Methoden zum Lesen und Schreiben. Ich sende vom Client {"class":"server.PasswordHashRequest","login":"admin"}
und erwarte {"class":"server.PasswordHashResponse","xoredHash":"RV5GX1JVAwADBEVZWwFGTAhZQ1FGX1tYQ11ZVwA\u003d"}
. Mit dem gleichen Code kann ich jetzt ein Problem und andere Probleme ein paar Minuten später bekommen. Ich habe alles versucht, was ich weiß. Habe ich es geschafft, segfault in Java zu bekommen?
Client-Seite Code:
@Test
public void main() throws Exception {
System.out.println("Opening socket");
InetSocketAddress socketAddress = new InetSocketAddress("localhost", 9090);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
Selector selector = Selector.open();
socketChannel.register(selector, OP_CONNECT);
socketChannel.connect(socketAddress);
PasswordHashRequest request = new PasswordHashRequest("admin");
System.out.println("Socket open");
while (true) {
System.out.println("Client selector awoken");
selector.select();
for (SelectionKey selectionKey : selector.selectedKeys()) {
if (selectionKey.isConnectable()) {
socketChannel.finishConnect();
selectionKey.interestOps(OP_WRITE);
} else if (selectionKey.isReadable()) {
String response = ServerManager.readMessage((SocketChannel) selectionKey.channel());
System.out.println(response);
server.interrupt();
} else if (selectionKey.isWritable()) {
ServerManager.sendMessage(request, (SocketChannel) selectionKey.channel());
System.out.println("Request sent");
selectionKey.interestOps(OP_READ);
}
}
}
}
Server-Side-Code:
public void run() {
System.out.println("Main thread started");
while (true) {
try {
// Get ready channels
int readyChannels = selector.select();
if (readyChannels == 0) { continue; }
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
// Handle Events
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
// New Client
if (key.isAcceptable()) {
System.out.println("New Client Accepted");
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
serverSocketChannel.configureBlocking(false);
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
SelectionKey clientKey = socketChannel.register(selector, SelectionKey.OP_READ);
Random randomInt = new Random(System.currentTimeMillis());
clientKey.attach(randomInt.nextInt(Integer.SIZE - 1));
}
// Client has sent data
else if (key.isReadable()) {
handleInput(key);
}
keyIterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Read-Methode:
public static String readMessage(SocketChannel socketChannel) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(16);
byteBuffer.clear();
StringBuilder stringBuilder = new StringBuilder();
int bytesRead = socketChannel.read(byteBuffer);
while (bytesRead != -1) {
byteBuffer.flip();
String byteString = new String(byteBuffer.array(), Charset.forName("UTF-8"));
stringBuilder.append(byteString);
byteBuffer.clear();
bytesRead = socketChannel.read(byteBuffer);
}
socketChannel.shutdownInput();
return stringBuilder.toString();
}
Write-Methode:
public static void writeMessage(String message, SocketChannel channel) throws IOException {
message += "\r\n";
System.out.println(message);
int bufferLength = 16;
byte[] responseBytes = message.getBytes();
int offset = 0;
ByteBuffer buf = ByteBuffer.allocate(bufferLength);
while (responseBytes.length > offset) {
buf.clear();
int div = responseBytes.length - offset;
if (div >= bufferLength) {
buf.put(responseBytes, offset, bufferLength);
} else {
buf.put(responseBytes, offset, div);
}
buf.flip();
channel.write(buf);
offset += bufferLength;
}
channel.shutdownOutput();
}
Vielen Dank, ich werde es heute versuchen. –