版权声明:本文为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();
}
}