简体   繁体   English

在Java中使用AsynchronousSocketChannel

[英]Using AsynchronousSocketChannel in Java

When using AsynchronousSocketChannel in Java, how do we read() without calling these functions? 在Java中使用AsynchronousSocketChannel时,如何在不调用这些函数的情况下读取()? I test read/write with netcat but it's supposed to be asynchronous so I would assume that a call to read() will not terminate. 我使用netcat测试了读/写操作,但是它应该是异步的,因此我假设对read()的调用不会终止。 Should I be using it differently? 我应该以其他方式使用它吗? If I use read() in a loop, it gives an exception "java.nio.channels.ReadPendingException" which makes me think that the first read() was not completed but the second tried to read() instead of the first read() waiting to complete. 如果我在循环中使用read(),它会给出一个异常“ java.nio.channels.ReadPendingException”,这使我认为第一个read()未完成,但是第二个尝试了read()而不是第一个read() )等待完成。

I am trying to understand a snippet I found on a site but I modified it to be simpler: 我试图了解我在网站上找到的代码段,但我对其进行了修改以使其更简单:

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

}

I call it in main() like this: 我在main()中这样称呼它:

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

With just this ^, the client terminates without bothering to read if the server didn't send anything yet 如果服务器还没有发送任何内容,则仅使用此^即可终止客户端,而无需进行任何读取

For both reading and writing you need to maintain 3 variables: 对于读写,您需要维护3个变量:

  • an input queue of buffers for reading/writhing 用于读取/写入的缓冲区输入队列

  • a boolean flag indicating the channel is free (no pending read/write now). 一个布尔型标志,指示通道空闲(现在没有挂起的读/写操作)。

  • an output queue of buffers 缓冲区的输出队列

if the channel is busy, put buffer in the input queue, otherwise start I/O operation. 如果通道繁忙,则将缓冲区放入输入队列中,否则开始I / O操作。 When the I/O operation completes, it puts its buffer in the output queue, and then examines the input queue. I / O操作完成时,它将其缓冲区放入输出队列中,然后检查输入队列。 If it is empty, the flag is set to true, otherwise next buffer is taken from the input queue and operations is restarted. 如果为空,则将标志设置为true,否则将从输入队列中获取下一个缓冲区并重新启动操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM