简体   繁体   English

异步NIO:同一客户端向服务器发送多条消息

[英]Async NIO: Same client sending multiple messages to Server

Regarding Java NIO2. 关于Java NIO2。

Suppose we have the following to listen to client requests... 假设我们有以下内容来监听客户的请求...

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

This code will accept a client connection process it and then accept another. 此代码将接受它的客户端连接过程,然后接受另一个。 To communicate with the server the client opens up an AsyncSocketChannel and fires the message. 为了与服务器通信,客户端打开一个AsyncSocketChannel并触发该消息。 The Completion handler completed() method is then invoked. 然后调用完成处理程序completed()方法。

However, this means if the client wants to send another message on the same AsyncSocket instance it can't. 但是,这意味着如果客户端要在同一AsyncSocket实例上发送其他消息,则不能。

It has to create another AsycnSocket instance - which I believe means another TCP connection - which is performance hit. 它必须创建另一个AsycnSocket实例-我认为这意味着另一个TCP连接-性能受到影响。

Any ideas how to get around this? 任何想法如何解决这个问题?

Or to put the question another way, any ideas how to make the same asyncSocketChannel receive multipe CompleteionHandler completed() events? 还是换种说法,有什么想法可以使相同的asyncSocketChannel接收多倍的CompleteionHandlercompleted()事件?

edit: My handling code is like this... 编辑:我的处理代码是这样的...

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

So that's it my server reads a message from the async channe and returns an answer. 就是这样,我的服务器从异步通道读取消息并返回答案。 The client blocks until it gets the answer. 客户端阻塞直到得到答案。 But this is ok. 但这没关系。 I don't care if client blocks. 我不在乎客户端是否阻止。

Whent this is finished, client tries to send another message on same async channel and it doesn't work. 完成此操作后,客户端尝试在同一异步通道上发送另一条消息,并且该消息不起作用。

There are 2 phases of connection and 2 different kind of completion handlers. 有2个阶段的连接和2种不同的完成处理程序。 First phase is to handle a connection request, this is what you have programmed (BTW as Jonas said, no need to use another executor). 第一阶段是处理连接请求,这是您已编写的程序(如乔纳斯所说,顺便说一句,无需使用其他执行程序)。 Second phase (which can be repeated multiple times) is to issue an I/O request and to handle request completion. 第二阶段(可以重复多次)是发出I / O请求并处理请求完成。 For this, you have to supply a memory buffer holding data to read or write, and you did not show any code for this. 为此,您必须提供一个存储缓冲区以保存要读取或写入的数据,并且没有为此显示任何代码。 When you do the second phase, you'll see that there is no such problem as you wrote: "if the client wants to send another message on the same AsyncSocket instance it can't". 当您进行第二阶段时,您将看到没有这样写的问题:“如果客户端希望在同一AsyncSocket实例上发送另一条消息,则不能。”

One problem with NIO2 is that on one hand, programmer have to avoid multiple async operations of the same kind (accept, read, or write) on the same channel (or else an error occur), and on the other hand, programmer have to avoid blocking wait in handlers. NIO2的一个问题是,一方面,程序员必须避免在同一通道上进行多次相同类型的异步操作(接受,读取或写入)(否则会发生错误),另一方面,程序员必须避免避免阻塞处理程序中的等待。 This problem is solved in df4j-nio2 subproject of the df4j actor framework , where both AsyncServerSocketChannel and AsyncSocketChannel are represented as actors. df4j actor框架的 df4j-nio2子项目中解决了此问题,其中AsyncServerSocketChannel和AsyncSocketChannel都表示为actor。 (df4j is developed by me.) (df4j由我开发。)

First, you should not use an executer like you have in the completed -method. 首先,您不应使用已completed -method中的执行程序。 The completed -method is already handled in a new worker-thread. completed -方法已经在新的工作线程中处理。

In your completed -method for .accept(...) , you should call asychSocketChannel.read(...) to read the data. completed.accept(...) ,应调用asychSocketChannel.read(...)读取数据。 The client can just send another message on the same socket. 客户端可以只在同一套接字上发送另一条消息。 This message will be handled with a new call to the completed -method, perhaps by another worker-thread on your server. 该消息将通过对completed方法的新调用来处理,这可能是由服务器上的另一个工作线程执行的。

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

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