在AIO中,服务端通过
asynchronousServerSocketChannel.accept(this,new AcceptCompletionHandler());
的方式接收客户端的连接,那它是怎么做的呢,我们做下源码分析。
这个accept方法进入了实现类
AsynchronousServerSocketChannelImpl的accept方法,如下:
public final <A> void accept(A var1, CompletionHandler<AsynchronousSocketChannel, ? super A> var2) {
if(var2 == null) {
throw new NullPointerException("\'handler\' is null");
} else {
this.implAccept(var1, var2);
}
}
implAccept方法是在它的子类WindowsAsynchronousServerSocketChannelImpl类中,为什么是这个类呢,因为在asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();我们打开AIOChannel的时候,返回的就是WindowsAsynchronousServerSocketChannelImpl类。在它的implAccept方法中,最重要的是下面这一段:
var3 = new WindowsAsynchronousSocketChannelImpl(this.iocp, false);它以new 的WindowsAsynchronousSocketChannelImpl,PendingFuture为参数,创建了一个任务类:AcceptTask,并最后将结果放入了PendingFuture中,返回回去。最重要的是AccessControlContext var5 = System.getSecurityManager() == null?null:AccessController.getContext(); PendingFuture var6 = new PendingFuture(this, var2, var1); WindowsAsynchronousServerSocketChannelImpl.AcceptTask var7 = new WindowsAsynchronousServerSocketChannelImpl.AcceptTask(var3, var5, var6); var6.setContext(var7); if(!this.accepting.compareAndSet(false, true)) { throw new AcceptPendingException(); } else { if(Iocp.supportsThreadAgnosticIo()) { var7.run(); } else { Invoker.invokeOnThreadInThreadPool(this, var7); } return var6;
AcceptTask的run方法,其代码最重要的是下面这个两行:
this.result.setResult(this.channel);在completed方法中有两个参数,var2是我们传入的SocketChannel用来处理客户端通讯,一个是我们前面的执行accept方法的handler,在completed方法中,我们要再次执行Invoker.invokeIndirectly(this.result);先是把channel放入了PenddingFature中,然后用Invoker去执行。最后进入了Invoker的invokeUnchecked方法,如下:static <V, A> void invokeUnchecked(CompletionHandler<V, ? super A> var0, A var1, V var2, Throwable var3) { if(var3 == null) { var0.completed(var2, var1); } else { var0.failed(var3, var1); } Thread.interrupted();
一遍accept方法,因为每次accept只能与一个客户端通信,并且处理接收请求的线程最后都被标记为interrupted。所以每次accept方法要重新注册使用。以上就是AIOaccept方法的源码分析,虽然介绍的有些地方不是特别详细,但是对于有点基础,想研究下的人来说足够使用了。