在Java中使用AsynchronousSocketChannel

时间:2018-05-24 05:13:52

标签: java asynchronous nio

在Java中使用AsynchronousSocketChannel时,如何在不调用这些函数的情况下read()?我用netcat测试读/写,但它应该是异步的,所以我假设对read()的调用不会终止。我应该以不同的方式使用它吗?如果我在循环中使用read(),它会给出异常" java.nio.channels.ReadPendingException"这让我觉得第一个read()没有完成,但是第二个尝试read()而不是第一个read()等待完成。

我正在尝试了解我在网站上找到的代码片段,但我将其修改为更简单:

public class EchoClient {

    public AsynchronousSocketChannel sockChannel;

    public EchoClient(String host, int port) throws IOException {
        sockChannel = AsynchronousSocketChannel.open();

        sockChannel.connect( new InetSocketAddress(host, port), sockChannel, new CompletionHandler<Void, AsynchronousSocketChannel >() {
            @Override
            public void completed(Void result, AsynchronousSocketChannel channel ) {
                System.out.println( "success");
            }

            @Override
            public void failed(Throwable exc, AsynchronousSocketChannel channel) {
                System.out.println( "failed to connect to server");
            }

        });
    }

    public void startRead() {
        final ByteBuffer buf = ByteBuffer.allocate(2048);

        sockChannel.read( buf, sockChannel, new CompletionHandler<Integer, AsynchronousSocketChannel>(){

            @Override
            public void completed(Integer result, AsynchronousSocketChannel channel) {
                //print the message
                System.out.println( "Read message:" + new String( buf.array()) );
            }

            @Override
            public void failed(Throwable exc, AsynchronousSocketChannel channel) {
            }

        });

    }

    public void write(final String message) {
        ByteBuffer buf = ByteBuffer.allocate(2048);
        buf.put(message.getBytes());
        buf.flip();
        sockChannel.write(buf, sockChannel, new CompletionHandler<Integer, AsynchronousSocketChannel >() {
            @Override
            public void completed(Integer result, AsynchronousSocketChannel channel ) {

            }

            @Override
            public void failed(Throwable exc, AsynchronousSocketChannel channel) {
                System.out.println( "Fail to write the message to server");
            }
        });
    }

}

我在main()中调用它:

EchoClient echo = new EchoClient( "127.0.0.1", 3000, "echo test");
echo.startRead();
echo.write("hi");

只有这个^,如果服务器还没有发送任何内容,客户端会终止而无需阅读

1 个答案:

答案 0 :(得分:0)

对于阅读和写作,您需要维护3个变量:

  • 用于读取/扭动的缓冲区的输入队列

  • 一个布尔标志,表示该频道是免费的(现在没有待处理的读/写)。

  • 缓冲区的输出队列

如果通道忙,则将缓冲区放入输入队列,否则启动I / O操作。当I / O操作完成时,它将其缓冲区放在输出队列中,然后检查输入队列。如果为空,则将该标志设置为true,否则从输入队列中取出下一个缓冲区并重新开始操作。