简体   繁体   English

java.nio的单个实例AsynchronousSocketChannel用于多个读写

[英]single instance of java.nio AsynchronousSocketChannel for multiple read and write

I read in the documentation that AsynchronousSocketChannel is threadsafe, so it is safe for single instance of it to be shared by multiple threads, but when I try to implement this single instance concept (in client side application) I failed to use write() method to send data to server. 我在文档中读到AsynchronousSocketChannel是线程安全的,因此它的单个实例由多个线程共享是安全的,但是当我尝试实现此单个实例概念(在客户端应用程序中)时,我无法使用write()方法发送数据到服务器。

Previously I had success doing it by calling shutdownOutput() or close() from channel after calling write(byteBuffer,attachment,completionHandler) . But when I just want to use only single instance without calling 以前,我通过close() from channel after calling write(byteBuffer,attachment,completionHandler) close() from channel after calling调用shutdownOutput()close() from channel after calling成功. But when I just want to use only single instance without calling . But when I just want to use only single instance without calling close() or shutdownOutput()` the message never reaches the server (I saw it from server log). . But when I just want to use only single instance without calling close() or shutdownOutput()`时,消息永远不会到达服务器(我从服务器日志中看到了)。

Do we need to close channel in order to make message reach the server? 我们是否需要关闭频道以使消息到达服务器? I use Spring boot to build this project. 我使用Spring boot来构建这个项目。

Here is my code: 这是我的代码:

@Component
public class AgentStatusService {


   private static final Logger log = 
   LoggerFactory.getLogger(AgentStatusService.class);

   @Autowired
   private SocketAddress serverAddress;
   @Autowired
   private AsynchronousSocketChannel channel;

   public void consumeMessage() throws IOException {


  try {

    log.info("trying to connect to {}", serverAddress.toString());
    channel.connect(serverAddress, channel, new SocketConnectCompletionHandler());
    log.info("success connect to {}", channel.getRemoteAddress());

  } catch (final AlreadyConnectedException ex) {

    final ByteBuffer writeBuffer = ByteBuffer.wrap("__POP  ".getBytes());

    final Map<String, Object> attachm`enter code here`ent = new HashMap<>();
    attachment.put("buffer", writeBuffer);
    attachment.put("channel", channel);

    writeBuffer.flip();
    channel.write(writeBuffer, attachment, new SocketWriteCompletionHandler());

  } catch (final Exception e) {
    log.error("an error occured with message : {}", e.getMessage());
    e.printStackTrace();
  }
}

This is my socket connect completion handler class: 这是我的套接字连接完成处理程序类:

   public class SocketConnectCompletionHandler
   implements CompletionHandler<Void, AsynchronousSocketChannel> {

   private static Logger log = 
   LoggerFactory.getLogger(SocketConnectCompletionHandler.class);

   @Override
   public void completed(Void result, AsynchronousSocketChannel channel) {

   try {

   log.info("connection to {} established", channel.getRemoteAddress());

   final ByteBuffer writeBuffer = ByteBuffer.wrap("__POP  ".getBytes());

   final Map<String, Object> attachment = new HashMap<>();
   attachment.put("buffer", writeBuffer);
   attachment.put("channel", channel);

    writeBuffer.flip();
    channel.write(writeBuffer, attachment, new 
    SocketWriteCompletionHandler());

  } catch (final IOException e) {
    e.printStackTrace();
  }

}

@Override
public void failed(Throwable exc, AsynchronousSocketChannel attachment) {
 exc.printStackTrace();

 try {
  log.error("connection to {} was failed", attachment.getRemoteAddress());
 } catch (final Exception e) {
  log.error("error occured with message : {}", e.getCause());
 }

 }

}

This is my socket write completion handler class: 这是我的套接字写完成处理程序类:

   public class SocketWriteCompletionHandler
   implements CompletionHandler<Integer, Map<String, Object>> {

     private static final Logger log = 
     LoggerFactory.getLogger(SocketWriteCompletionHandler.class);

     @Override
     public void completed(Integer result, Map<String, Object> attachment) {

       try {

       final AsynchronousSocketChannel channel =
        (AsynchronousSocketChannel) attachment.get("channel");


       final ByteBuffer buffer = (ByteBuffer) attachment.get("buffer");
        log.info("write {} request to : {}", new String(buffer.array()), 
        channel.getRemoteAddress());
        buffer.clear();

        readResponse(channel, buffer);



       } catch (final Exception ex) {
          ex.printStackTrace();
          log.error("an error occured with message : {}", ex.getMessage());
       }

     }

  @Override
  public void failed(Throwable exc, Map<String, Object> attachment) {

      log.error("an error occured : {}", exc.getMessage());

   }


    public void readResponse(AsynchronousSocketChannel channel, ByteBuffer 
    writeBuffer) {


       final ByteBuffer readBuffer = ByteBuffer.allocate(2 * 1024);
       final Map<String, Object> attachment = new HashMap<>();
       attachment.put("writeBuffer", writeBuffer);
       attachment.put("readBuffer", readBuffer);
       attachment.put("channel", channel);

       readBuffer.flip();
       channel.read(readBuffer, attachment, new 
           SocketReadCompletionHandler());

     }

   }

If the server thinks it didn't receive the message, and it did when you were previously shutting down or closing the socket, it must be trying to read to end of stream, and blocking or at least not completing its read and so never logging anything. 如果服务器认为它没有收到消息,并且在您之前关闭或关闭套接字时确实发生了,则它必须尝试读取到流的末尾,并且阻塞或至少没有完成其读取,因此永远不要记录日志任何东西。

Why you are using multiple threads in conjunction with asynchronous I/O, or indeed with any socket, remains a mystery. 为什么将多个线程与异步I / O或实际上与任何套接字一起使用仍然是个谜。

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

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