2017-06-03 2 views
1

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(); 
} 

Antwort

2
  • Ihre Lesemethode sollte aufhören zu lesen, wenn bytesRead <= 0
  • Es Konto der Puffergrenze nehmen soll, wenn die Zeichenfolge
  • Methode
  • Ihrer Schreib Konstruktion sollte Schreib aufhören zu versuchen, wenn write() Null zurückgibt, und dann (und nur dann) Register den Kanal für OP_WRITE, und nur weiterschreiben, wenn es ausgelöst wird.

Siehe viele ähnliche Fragen hier zu all dem.

+0

Vielen Dank, ich werde es heute versuchen. –

Verwandte Themen