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