简体   繁体   中英

Async NIO: Same client sending multiple messages to Server

Regarding 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. The Completion handler completed() method is then invoked.

However, this means if the client wants to send another message on the same AsyncSocket instance it can't.

It has to create another AsycnSocket instance - which I believe means another TCP connection - which is performance hit.

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?

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. 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. 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".

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. This problem is solved in df4j-nio2 subproject of the df4j actor framework , where both AsyncServerSocketChannel and AsyncSocketChannel are represented as actors. (df4j is developed by me.)

First, you should not use an executer like you have in the completed -method. The completed -method is already handled in a new worker-thread.

In your completed -method for .accept(...) , you should call asychSocketChannel.read(...) to read the data. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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