深入阅读Mina源码(3) —— Mina之IOAdapter(二)

来源:互联网 发布:vc ado access数据库 编辑:程序博客网 时间:2024/06/06 15:47

深入阅读Mina源码(3) —— Mina之IOAdapter(二)


 

4. AbstractPollingIoAcceptor

 

     这个类在org.apache.mina.core.polling,这个包一共有四个类,这个类就可以代表整个包的内容了,细致说一下,之后就不再深入介绍这个包了。从名字可以看出包里面的类主要完成轮询。

     AbstractPollingIoAcceptor主要完成了AbstractIoAcceptor定义的实际实现方法,如unbind0、bindInternal、dispose0,另外下方了一些更细致的accept、open、select、colse方法让子类实现,也清晰的可以看出它主要为Socket提供父类的一些实现,同时也有了NIO的影子。

     看一下AbstractPollingIoAcceptor的属性字段,可以看到

 

 

Java代码  收藏代码
  1. /** A lock used to protect the selector to be waked up before it's created */  
  2.     private final Semaphore lock = new Semaphore(1);  
  3.   
  4.     private final IoProcessor<S> processor;  
  5.   
  6.     private final boolean createdProcessor;  
  7.   
  8.     private final Queue<AcceptorOperationFuture> registerQueue = new ConcurrentLinkedQueue<AcceptorOperationFuture>();  
  9.   
  10.     private final Queue<AcceptorOperationFuture> cancelQueue = new ConcurrentLinkedQueue<AcceptorOperationFuture>();  
  11.   
  12.     private final Map<SocketAddress, H> boundHandles = Collections.synchronizedMap(new HashMap<SocketAddress, H>());  
  13.   
  14.     private final ServiceOperationFuture disposalFuture = new ServiceOperationFuture();  
  15.   
  16.     /** A flag set when the acceptor has been created and initialized */  
  17.     private volatile boolean selectable;  
  18.   
  19.     /** The thread responsible of accepting incoming requests */  
  20.     private AtomicReference<Acceptor> acceptorRef = new AtomicReference<Acceptor>();  
  21.   
  22.     protected boolean reuseAddress = false;  
  23.   
  24.     /** 
  25.      * Define the number of socket that can wait to be accepted. Default 
  26.      * to 50 (as in the SocketServer default). 
  27.      */  
  28.     protected int backlog = 50;  
 

    这个类讲下去确实有种无从下手的感觉,这里注意一个acceptorRef是处理请求的AtomicReference类型的Acceptor,Acceptor是一个用于接收客户端请求,里面代码比较多,但是我感觉此部分是整个类比较关键的实现部分,需要仔细读一下,但是实在不太好讲,这里可以同样只关注整体,不关注细节,包括processor一些方法的内部完成。我只总结一个流程:

 

 

    主要的两个方法把父类中的注释写一下,方便理解,看了注释再看代码就比较容易想明白了:

 

    bindInternal:Starts the acceptor, and register the given addresses

    unbind0:Implement this method to perform the actual unbind operation.

 

 

5. NioSocketAcceptor

 

    终于,到这个最终的类了,我们也将要看到作为NIO部分我们最希望看到的一系列东西。看到导入的一堆java.nio.channels.*感觉好舒服,马上整个流程的谜底既要揭开了。代码非常少,更欣慰。

 

 

Java代码  收藏代码
  1. protected NioSession accept(IoProcessor<NioSession> processor, ServerSocketChannel handle) throws Exception {  
  2.   
  3.         SelectionKey key = handle.keyFor(selector);  
  4.   
  5.         if ((key == null) || (!key.isValid()) || (!key.isAcceptable())) {  
  6.             return null;  
  7.         }  
  8.   
  9.         // accept the connection from the client  
  10.         SocketChannel ch = handle.accept();  
  11.   
  12.         if (ch == null) {  
  13.             return null;  
  14.         }  
  15.   
  16.         return new NioSocketSession(this, processor, ch);  
  17. }  
 

 

    可以看到这里已经和Nio包内的方法对应起来了,实现的内容也相对比较简单是Nio包的一个事例一样。

    既然不复杂只是Nio包内的内容的话,我们就来看一下这一串流程是怎么运行下来的,也是NioSocketAcceptor能只是简单的利用Nio已有的功能实现Nio的Acceptor的原因。

 

    回顾一下实际使用的时候是调用的:acceptor.bind(new InetSocketAddress(SERVER_PORT)),指定服务提供绑定的端口。

    通过上面那么多的分析,我们知道了同时执行了AbstractPollingIoAcceptor中的bindInternal方法, 其中调用startupAcceptor(),因为是第一次,就负责初始化了内部线程类Acceptor。

    Acceptor主要负责轮询处理注册过连接事件的请求建立起连接,即整个监听的主线程,Acceptor会开一个Selector,用来监听NIO中的ACCEPT事件,调用NioSocketAcceptor中的open()方法来打开NIO的socketChannel(在AbstractPollingIoAcceptor的registerHandles方法调用,即前面图中的第二步,这里才真正的把Selector设为OP_ACCEPT)。

 

 

Java代码  收藏代码
  1. protected ServerSocketChannel open(SocketAddress localAddress) throws Exception {  
  2.         // Creates the listening ServerSocket  
  3.         ServerSocketChannel channel = ServerSocketChannel.open();  
  4.   
  5.         boolean success = false;  
  6.   
  7.         try {  
  8.             // This is a non blocking socket channel  
  9.             channel.configureBlocking(false);  
  10.   
  11.             // Configure the server socket,  
  12.             ServerSocket socket = channel.socket();  
  13.   
  14.             // Set the reuseAddress flag accordingly with the setting  
  15.             socket.setReuseAddress(isReuseAddress());  
  16.   
  17.             // and bind.  
  18.             socket.bind(localAddress, getBacklog());  
  19.   
  20.             // Register the channel within the selector for ACCEPT event  
  21.             channel.register(selector, SelectionKey.OP_ACCEPT);  
  22.             success = true;  
  23.         } finally {  
  24.             if (!success) {  
  25.                 close(channel);  
  26.             }  
  27.         }  
  28.         return channel;  
  29. }  
 

 

 

6. final

 

    感觉第一次阅读整个开源框架,还有些把握不住主线和方法,使得整个博文我看起来也有点杂乱无章的感觉,但希望有助于一步步看代码的嘶吼帮助下理解和把握整体逻辑吧。接下来几天还要考试,又要好哈复习了,抽了一晚上时间弄完了这部分代码,感觉两次看代码中间时间间隔太长是有很大影响了,还是应该连续的看一部。好了,不多说了,希望有帮助,复习去了,几天后继续阅读下一部分代码。

阅读全文
0 0
原创粉丝点击