AIO,A是Asynchronous 异步的。只要是异步,一定是不会阻塞住主线程,也一定是要有回调函数。
具体server端的示例代码如下:
public class Server {
public static void main(String[] args) throws Exception {
AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8888));
serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
@Override
public void completed(AsynchronousSocketChannel client, Object attachment) {
serverChannel.accept(null, this);
try {
System.out.println(client.getRemoteAddress());
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
attachment.flip();
System.out.println(new String(attachment.array(),0,result));
client.write(ByteBuffer.wrap("HelloClient".getBytes()));
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Object attachment) {
exc.printStackTrace();
}
});
System.out.println("服务已启动");
while(true){
Thread.sleep(1000);
}
}
}
BIO的server端创建的是ServerSocket对象
NIO的server端创建的是ServerSocketChannel对象
AIO的server端创建的是AsynchronousServerSocketChannel对象(简称assc)。
对于AIO,assc的accept是异步方法,方法的第二参数就是其回调方法。回调方法就是accept先执行,执行完,后续的逻辑都是在回调函数中实现,实际上就是类似注册了一个监听方法,就是这个回调方法。第一个accept方法有点类似nio的selector.select();
由于是异步方法,所以主线程中加了while(true)的循环,不加的话,主线程结束,服务端整个就结束了,也就不会有什么回调函数的执行了。
在回调方法中,会获取到AsynchronousSocketChannel对象(简称asc),它跟assc实现了相同的接口。可以看下类图:
在assc的回调方法里面,使用assc.accept(null,this);来实现递归,目的是用当前回调函数的匿名对象继续接收后续的客户端请求。assc的accept参数里的回调函数对象,有点类似NIO的Selector,也是一个多路复用器。
使用asc的对象的read和write分别进行读取客户端的数据以及写会给客户端数据。