关于Java NIO2。
假设我们有以下内容来收听客户请求...
asyncServerSocketChannel.accept(null, new CompletionHandler <AsynchronousSocketChannel, Object>() {
@Override
public void completed(final AsynchronousSocketChannel asyncSocketChannel, Object attachment) {
// Put the execution of the Completeion handler on another thread so that
// we don't block another channel being accepted.
executer.submit(new Runnable() {
public void run() {
handle(asyncSocketChannel);
}
});
// call another.
asyncServerSocketChannel.accept(null, this);
}
@Override
public void failed(Throwable exc, Object attachment) {
// TODO Auto-generated method stub
}
});
此代码将接受客户端连接进程,然后接受另一个。 要与服务器通信,客户端将打开AsyncSocketChannel并触发消息。 然后调用Completion处理程序completed()方法。
但是,这意味着如果客户端想要在同一个AsyncSocket实例上发送另一个消息,则不能。
它必须创建另一个AsycnSocket实例 - 我认为这意味着另一个TCP连接 - 这会影响性能。
任何想法如何解决这个问题?
或者以另一种方式提出问题,任何想法如何使同样的asyncSocketChannel接收多重CompleteionHandler completed()事件?
编辑: 我的处理代码是这样的......
public void handle(AsynchronousSocketChannel asyncSocketChannel) {
ByteBuffer readBuffer = ByteBuffer.allocate(100);
try {
// read a message from the client, timeout after 10 seconds
Future<Integer> futureReadResult = asyncSocketChannel.read(readBuffer);
futureReadResult.get(10, TimeUnit.SECONDS);
String receivedMessage = new String(readBuffer.array());
// some logic based on the message here...
// after the logic is a return message to client
ByteBuffer returnMessage = ByteBuffer.wrap((RESPONSE_FINISHED_REQUEST + " " + client
+ ", " + RESPONSE_COUNTER_EQUALS + value).getBytes());
Future<Integer> futureWriteResult = asyncSocketChannel.write(returnMessage);
futureWriteResult.get(10, TimeUnit.SECONDS);
} ...
这就是我的服务器从异步通道读取消息并返回一个答案。 客户端阻止,直到它得到答案。但这没关系。我不在乎客户阻止。
完成此操作后,客户端会尝试在同一个异步通道上发送另一条消息,但它不起作用。
答案 0 :(得分:3)
有两个连接阶段和两种不同类型的完成处理程序。 第一阶段是处理连接请求,这是您编写的(BTW,如Jonas所说,不需要使用其他执行程序)。第二阶段(可以重复多次)是发出I / O请求并处理请求完成。为此,您必须提供一个内存缓冲区来保存要读取或写入的数据,并且您没有显示任何代码。当你进行第二阶段时,你会发现你写的没有这样的问题:“如果客户端想要在同一个AsyncSocket实例上发送另一个消息,那就不能了。”
NIO2的一个问题是,一方面,程序员必须避免在同一个通道上进行同一类型的多个异步操作(接受,读取或写入)(否则会发生错误),另一方面,程序员必须避免在处理程序中阻塞等待。这个问题在df4j actor framework的df4j-nio2子项目中得到解决,其中AsyncServerSocketChannel和AsyncSocketChannel都表示为actor。 (df4j由我开发。)
答案 1 :(得分:1)
首先,您不应该使用completed
方法中的执行器。 completed
- 方法已在新的工作线程中处理。
在completed
的{{1}}方法中,您应该致电.accept(...)
来阅读数据。客户端可以在同一个套接字上发送另一条消息。此消息将通过对asychSocketChannel.read(...)
- 方法的新调用来处理,可能由服务器上的另一个工作线程处理。