Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中使用异步socketchannel_Java_Asynchronous_Nio - Fatal编程技术网

在Java中使用异步socketchannel

在Java中使用异步socketchannel,java,asynchronous,nio,Java,Asynchronous,Nio,在Java中使用AsynchronousSocketChannel时,如何在不调用这些函数的情况下读取()?我用netcat测试读/写,但它应该是异步的,所以我假设对read()的调用不会终止。我应该用不同的方式吗?如果我在循环中使用read(),它会给出一个异常“java.nio.channels.ReadPendingException”,这使我认为第一个read()没有完成,但第二个read()尝试了read(),而不是等待完成的第一个read() 我试图理解我在一个网站上找到的一个片段,

在Java中使用AsynchronousSocketChannel时,如何在不调用这些函数的情况下读取()?我用netcat测试读/写,但它应该是异步的,所以我假设对read()的调用不会终止。我应该用不同的方式吗?如果我在循环中使用read(),它会给出一个异常“java.nio.channels.ReadPendingException”,这使我认为第一个read()没有完成,但第二个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");
            }
        });
    }

}

仅此^,如果服务器尚未发送任何内容,则客户端将终止,而不必费心读取。对于读取和写入,您需要维护3个变量:

  • 用于读/写的缓冲区的输入队列

  • 指示通道空闲的布尔标志(现在没有挂起的读/写)

  • 缓冲区的输出队列


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

您需要防止客户端退出,直到读取完成。你可以使用
Future
来代替完成处理程序。我试图避免使用Future。这是比CompletionHandler更好的方法吗?您可以在主线程上保留一个信号对象,然后等待
Socket
object”处理程序通知您。
EchoClient echo = new EchoClient( "127.0.0.1", 3000, "echo test");
echo.startRead();
echo.write("hi");