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

版权声明:本文为Zhang Phil原创文章,请不要转载! https://blog.csdn.net/zhangphil/article/details/88188043

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

猜你喜欢

转载自blog.csdn.net/zhangphil/article/details/88188043