在Java中使用阻塞NIO

时间:2016-05-09 18:57:15

标签: java nio socketchannel

我只是想知道是否可以使用SocketChannel类(使用ByteBuffer)来模拟Java中常规Socket类的阻塞功能。我制作了两个测试项目,一个模拟客户端,另一个模拟服务器:

客户代码:

    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,其中更改为-1或4(字节)在整数)。

至于服务器端,我知道我可以让它等待,以便第二个socketCh.read(缓冲区)返回一个非-1的值,这意味着在SocketChannel中没有写入(我推测)。

然而,在客户端,我没有任何想法。

我知道我可以使用DataOutputStream和DataInputStream来做旧方式,但我想知道如何使用SocketChannels来简化方便。另外,你可以通过另一种技巧来解决问题。

即使我手动将服务器配置为阻止,我也认为它是默认配置,因此可以将其丢弃。

提前谢谢! PS:希望我能避免使用Selector类来完成这么简单的任务......

编辑:我知道Selector类只能用于非阻塞模式。

1 个答案:

答案 0 :(得分:1)

您丢弃了可能已读取的额外数据,并假设每次读取都准确地传达了与每次写入相对应的内容(例如,第一次只传送int)。 TCP中没有任何内容可以保证这一点。

rewind()更改为flip();将clear()更改为compact();添加一些read()的返回值检查;它应该按预期工作。

您无法在阻止模式下使用Selector