0

关于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 并触发消息。然后调用完成处理程序 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);
   } ...

这就是我的服务器从异步通道读取消息并返回答案。客户端阻塞,直到它得到答案。但这没关系。我不在乎客户端是否阻塞。

完成后,客户端尝试在同一异步通道上发送另一条消息,但它不起作用。

4

2 回答 2

3

有 2 个连接阶段和 2 种不同类型的完成处理程序。第一阶段是处理连接请求,这是您编写的程序(顺便说一句,正如乔纳斯所说,不需要使用另一个执行程序)。第二阶段(可以重复多次)是发出 I/O 请求并处理请求完成。为此,您必须提供一个内存缓冲区来保存要读取或写入的数据,并且您没有为此显示任何代码。当您执行第二阶段时,您会发现不存在您所写的问题:“如果客户端想要在同一个 AsyncSocket 实例上发送另一条消息,它就不能”。

NIO2 的一个问题是,一方面,程序员必须避免在同一通道上进行多个相同类型的异步操作(接受、读取或写入)(否则会发生错误),另一方面,程序员必须避免在处理程序中阻塞等待。这个问题在df4j actor framework的 df4j-nio2 子项目中得到解决,其中 AsyncServerSocketChannel 和 AsyncSocketChannel 都表示为 actor。(df4j 是我开发的。)

于 2012-10-22T20:21:44.163 回答
1

首先,您不应该像在 - 方法中那样使用执行completed器。-completed方法已经在一个新的工作线程中处理。

在你的completed-method for 中.accept(...),你应该调用asychSocketChannel.read(...)来读取数据。客户端可以在同一个套接字上发送另一条消息。此消息将通过对 - 方法的新调用来处理completed,可能由服务器上的另一个工作线程处理。

于 2012-10-22T19:15:53.230 回答