Java新AIO/NIO2:以CompletionHandler实现 AsynchronousServerSocketChannel服务器端

论坛 期权论坛 脚本     
匿名技术用户   2021-1-4 00:26   317   0

Java新AIO/NIO2:以CompletionHandler实现 AsynchronousServerSocketChannel服务器端程序代码

import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Server {
 private AsynchronousServerSocketChannel serverSocketChannel;
 
 public static void main(String[] args) {
  try {
   Server server = new Server();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 public Server() throws Exception {
  //AsynchronousChannelGroup group = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(),10);
  //serverSocketChannel = AsynchronousServerSocketChannel.open(group);
  serverSocketChannel = AsynchronousServerSocketChannel.open();

  InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost", 80);

  //serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
  //serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);

  serverSocketChannel.bind(inetSocketAddress);

  MyCompletionHandler completionHandler = new MyCompletionHandler();
  serverSocketChannel.accept(null, completionHandler);

  // AIO非阻塞,需要在主进程阻塞,否则进程退出导致套接字关闭,服务器接受不到任何连接。
  try {
   Thread.sleep(Integer.MAX_VALUE);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }

 private class MyCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {
  @Override
  public void completed(AsynchronousSocketChannel socketChannel, Object attachment) {
   System.out.println("服务器接受连接");
   try {
    sendDataToClient(socketChannel);
    
    serverSocketChannel.accept(null, this);
   } catch (Exception e) {
    e.printStackTrace();
   }
  }

  @Override
  public void failed(Throwable t, Object attachment) {
   t.printStackTrace();
  };
 }

 private void sendDataToClient(AsynchronousSocketChannel socketChannel) throws Exception {
  System.out.println("服务器与" + socketChannel.getRemoteAddress() + "建立连接");

  ByteBuffer buffer = ByteBuffer.wrap("zhangphil".getBytes());
  Future<Integer> write = socketChannel.write(buffer);

  while (!write.isDone()) {
   Thread.sleep(10);
  }

  System.out.println("服务器发送数据完毕.");
  socketChannel.close();
 }
}

用CompletionHandler实现 的AsynchronousServerSocketChannel服务器端程序代码,有一个问题在于需要额外的通过Thread.sleep(Integer.MAX_VALUE)让当前进程无限休眠,因为担心程序退出,程序不退出的前提下,才能够让
serverSocketChannel.accept(null, completionHandler);
继续可以回调接受来自客户端的连接,当客户端的连接请求在CompletionHandler完成后,继续在CompletionHandler的completed()里面调用accept()函数等待客户端连接请求。

这种方案必须保证程序不能退出,一旦退出就会导致应用进程被杀掉,那么serverSocketChannel.accept(null, completionHandler) 就完全失效。或者换成我前一篇写的那种形式:

while (true){
    Future<AsynchronousSocketChannel> future = serverSocketChannel.accept();
    AsynchronousSocketChannel socketChannel = null;
    try {
        socketChannel = future.get();
        socketChannel.write(ByteBuffer.wrap("zhangphil".getBytes()));
     }catch (Exception e){
        e.printStackTrace();
     }
}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP