2016-05-09 37 views
0

我只是想知道是否可以使用SocketChannel類(使用ByteBuffer)來模擬Java中的常規Socket類的阻塞特性。我做了兩個試驗項目,一個模擬客戶端和其他模擬服務器:在Java中使用阻塞NIO

客戶端代碼:

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

服務器代碼:

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

正如我在評論中說,該結果運行服務器時,客戶端(按該順序)是不可預知的,因爲有時第二個數字可能會保持爲4或變爲6,而Change分別爲-1或4(整數字節)。

至於服務器端,我知道我可以讓它等待,以便第二個socketCh.read(buffer)返回一個非-1的值,這意味着什麼都沒有被寫入(我推測)在SocketChannel中。

但是,在客戶端,我沒有任何想法。

我知道我可以改爲使用DataOutputStream和DataInputStream並以舊式方式進行,但我想知道如何使用SocketChannel來完成此操作,只是爲了方便起見。另外你也不會因爲另一個詭計而出錯。

儘管我手動將服務器配置爲阻塞,但我認爲這是默認配置,因此可以丟棄它。

預先感謝您! PS:希望我可以避免使用Selector類來完成這樣一個簡單的任務...

編輯:我知道Selector類只能用於非阻塞模式。

回答

1

您丟掉了可能已被讀取的額外數據,並假設每次讀取都提供與每次寫入相對應的內容(例如,第一次只傳遞int)。 TCP中沒有任何東西可以保證這一點。

rewind()更改爲flip();將clear()更改爲compact();添加一些read()返回值的檢查;它應該按預期工作。

您不能在阻止模式下使用Selector

+0

好的謝謝!是的,我知道你不能在阻塞模式下使用Selector,但是我希望避免必須將SocketChannel配置爲非阻塞,並且必須爲此簡單任務完成所有這些。 –

+0

現在我讀了一下compact()的細節,讓整個過程更加有意義。這就是我爲了掠過一本書而​​得到的結果,我想:\。謝謝你,真的很感激它 –