2016-05-09 15 views
0

Ich frage mich nur, ob es möglich ist, die SocketChannel-Klasse (mit ByteBuffer) zu verwenden, um die Blockierungsfunktionen der regulären Socket-Klasse in Java zu simulieren. Ich habe zwei Test-Projekte, eines der Client-Simulation und die andere Simulation des Server:Blockieren von NIO in Java

Client-Code:

public static void main(String[] args) throws IOException { 

    SocketChannel socket = SocketChannel.open(new InetSocketAddress("127.0.0.1", 6789)); 

    //Simulate this: 
    //DataOutputStream dos = new DataOutputStream(socket.socket().getOutputStream()); 
    //dos.writeInt(4); 
    //dos.writeInt(6); 

    ByteBuffer buffer = ByteBuffer.allocate(4); 
    buffer.putInt(4); 
    buffer.flip(); 
    socket.write(buffer); 
    buffer.clear(); 
    buffer.putInt(6); 
    buffer.flip(); 
    socket.write(buffer); 
} 

Server-Code:

public static void main(String[] args) throws IOException, InterruptedException { 
    ServerSocketChannel ssc = ServerSocketChannel.open(); 
    ssc.socket().bind(new InetSocketAddress(6789)); 
    SocketChannel socketCh = ssc.accept(); 
    socketCh.configureBlocking(true); 
    // Simulate this 
    // DataInputStream dis = new DataInputStream(socketCh.socket().getInputStream()); 
    // System.out.println(dis.readInt()); 
    // System.out.println(dis.readInt()); 

    // This is something to avoid. This is not the same as what is up above 
    // If the 2nd line prints -1, the 3rd prints 4 
    // If the 2nd line prints 4, the 3rd prints 6 
    ByteBuffer buffer = ByteBuffer.allocate(1024); 
    socketCh.read(buffer); 
    buffer.rewind(); 
    System.out.println("First number: " + buffer.getInt()); 
    buffer.clear(); 
    System.out.println("Change: " + socketCh.read(buffer)); 
    buffer.rewind(); 
    System.out.println("Second Number: " + buffer.getInt()); 
} 

Wie ich schon sagte in den Kommentaren, die Ergebnisse Wenn der Server ausgeführt wird, ist der Client (in dieser Reihenfolge) unvorhersehbar, da manchmal die zweite Nummer 4 bleiben oder 6 werden kann, wobei die Änderung -1 oder 4 (Bytes in Integer) ist.

Wie für die Server-Seite, ich weiß, ich kann es warten lassen, so dass der zweite socketCh.read (Puffer) einen anderen Wert als -1 zurückgibt, was bedeutet, dass nichts geschrieben wurde (ich vermute) in der SocketChannel.

Allerdings habe ich auf der Client-Seite keine Ideen.

Ich bin mir bewusst, dass ich stattdessen DataOutputStream und DataInputStream verwenden kann und es auf die altmodische Art und Weise tun, aber ich möchte einfach aus Bequemlichkeit für SocketChannels wissen, wie es geht. Auch Sie können nichts falsch machen mit einem weiteren Trick in Ihrem Ärmel.

Obwohl ich den Server manuell als Blockierung konfiguriert habe, nehme ich an, dass es sich um die Standardkonfiguration handelt, also ist es in Ordnung, sie zu verwerfen.

Vielen Dank im Voraus! PS: Hoffentlich könnte ich vermeiden, die Selector-Klassen für solch eine einfache Aufgabe zu verwenden ...

EDIT: Ich weiß, dass die Selector-Klassen können nur für nicht blockierende Modus verwendet werden.

Antwort

1

Sie werfen zusätzliche Daten weg, die möglicherweise gelesen wurden, und nehmen an, dass jeder Lesevorgang genau das liefert, was jedem Schreibvorgang entspricht (z. B. dass der erste nur die int liefert). Es gibt nichts in TCP, das das garantiert.

Ändern Sie die rewind() zu flip(); Ändern Sie die clear() zu compact(); fügen Sie eine Überprüfung des Rückgabewerts von read() hinzu; und es sollte wie erwartet funktionieren.

Sie können Selector nicht im Blockiermodus verwenden.

+0

Alles klar, danke! Ja, ich bin mir bewusst, dass Sie Selector nicht im Blocking-Modus verwenden können, aber ich wollte vermeiden, dass der SocketChannel nicht blockierend konfiguriert werden muss und all dies für diese einfache Aufgabe tun muss. –

+0

Macht eine ganze Tonne mehr Sinn, wenn ich jetzt lese, was compact() im Detail macht. Das ist, was ich für das Überfliegen eines Buches schätze, denke ich: \. Danke Mann, schätze es wirklich –

Verwandte Themen