Mina源码分析——IoService

来源:互联网 发布:python 连接sqlserver 编辑:程序博客网 时间:2024/06/06 00:03

   这两天看了下Mina和Netty的源码,想比较来说Mina的结构简洁易懂。Mina和Netty出自同一人,而Netty是作者对Mina的重构版,改进了很多。如果学习网络编程的话,个人建议从Mina开始,学完Mina后再看Netty,学习曲线会变得很平滑;同时还能深刻理解到作者改进点。 


   先看下Mina的结构图,如果之前做过java的web开发,熟悉servlet规范,看到这个结构图,会觉得非常亲切。这个结构描述了基本的网络开发结构。 



  • IoService  服务端和客户端I/O 操作的抽象,服务端为IoAcceptor,客户端为IoConnector
  • IoSession  封装了服务端与客服端连接的会话信息
  • IoFilterChain IoFilter处理链
  • IoFilter   对服务端和客户端交互的数据做处理
  • IoHandler  业务处理


好了,说了那么多还是先分析代码吧。Mina的客户端和服务端开发会略有不同,因为java网络编程的本身就是如此。我们先从分析服务器端开发入手。这里引用了Mina example中的Timer server,它的逻辑非常简单,就是接收到客户端的请求后,返回服务器的当前时间。 

TimerServerHandler.java 
Java代码  收藏代码
  1. public class TimeServerHandler extends IoHandlerAdapter {  
  2.   
  3.     @Override  
  4.     public void messageReceived(IoSession session, Object message) throws Exception {  
  5.         String msg = (String) message;  
  6.         if ("quit".equals(msg.trim())) {  
  7.             System.out.println("client " + session.getRemoteAddress() + " quited!");  
  8.             session.close(false);  
  9.             return;  
  10.         }  
  11.   
  12.         Date date = new Date();  
  13.         session.write(date.toString());  
  14.         System.out.println("message written...");  
  15.     }  
  16.   
  17. }  


开启服务器 
Java代码  收藏代码
  1. private static final int SERVER_PORT = 8888;  
  2.   
  3. public static void main(String[] args) throws IOException {  
  4.     IoAcceptor acceptor = new NioSocketAcceptor();  
  5.   
  6.     acceptor.getFilterChain().addLast("logging"new LoggingFilter());  
  7.     acceptor.getFilterChain().addLast("codec",  
  8.             new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));  
  9.   
  10.     acceptor.setHandler(new TimeServerHandler());  
  11.   
  12.     acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);  
  13.     acceptor.getSessionConfig().setReadBufferSize(2048);  
  14.   
  15.     acceptor.bind(new InetSocketAddress(SERVER_PORT));  
  16. }  


1、先创建一个IoAcceptor实例,这里创建的是一个基于tcp的Java NIO版的IoAccptor 
2、往FilterChain中追加了 LoggingFilter 和TextLineCodecFactory,LoggingFilter 可以对客户端的请求和服务器端的响应日志记录。TextLineCodecFactory 是一个协议编码解码器的工厂,就是将字节流与java中的String之间的相互转换。后面会详细介绍。 
3、添加一个TimerServerHandler实例。TimeServerHandler 处理的逻辑就是在接收到客户端发送过来的字符串信息后,判断如果是quit,关闭与客户端的链接。不是的就返回服务器的当前时间的字符串。 
4、设置一些IoSession的可配属性 
5、绑定到一个端口上,开始监听客户端的请求。 


上面我们只写了一个TimerServerHandler,并在messageReceived 方法中定义了自己的业务处理就轻松的完成了一个服务器端的开发,而不用去关心底层的链接和I/O处理,这就是mina的魅力所在,让开发人员从处理容易出错的I/O操作中解放出来。 

现在我们逐个分析代码中出现的一些类和方法。先看一个IoService的继承体系。Mina提供了丰富的实现,支持很多协议,IoService的继承体系没有下面简单。简单起见,上面的图中值画出了Server端的结构,分析IoServeric先从IoAcceptor入手,而且就分析我们熟悉的java nio相关的类。 

 

IoAcceptor是IoService在服务器端的一个抽象。先从接口的功能开始分析: 
Java代码  收藏代码
  1. public interface IoService {  
  2.   
  3.     TransportMetadata getTransportMetadata();  
  4.   
  5.     void addListener(IoServiceListener listener);  
  6.   
  7.     void removeListener(IoServiceListener listener);  
  8.   
  9.     boolean isDisposing();  
  10.   
  11.     boolean isDisposed();  
  12.   
  13.     void dispose();  
  14.   
  15.     void dispose(boolean awaitTermination);  
  16.   
  17.     IoHandler getHandler();  
  18.   
  19.     void setHandler(IoHandler handler);  
  20.   
  21.     Map<Long, IoSession> getManagedSessions();  
  22.   
  23.     int getManagedSessionCount();  
  24.   
  25.     IoSessionConfig getSessionConfig();  
  26.   
  27.     IoFilterChainBuilder getFilterChainBuilder();  
  28.   
  29.     void setFilterChainBuilder(IoFilterChainBuilder builder);  
  30.   
  31.     DefaultIoFilterChainBuilder getFilterChain();  
  32.   
  33.     boolean isActive();  
  34.   
  35.     long getActivationTime();  
  36.   
  37.     Set<WriteFuture> broadcast(Object message);  
  38.   
  39.     IoSessionDataStructureFactory getSessionDataStructureFactory();  
  40.   
  41.     void setSessionDataStructureFactory(IoSessionDataStructureFactory sessionDataStructureFactory);  
  42.   
  43.     int getScheduledWriteBytes();  
  44.   
  45.     int getScheduledWriteMessages();  
  46.   
  47.     IoServiceStatistics getStatistics();  
  48. }  


从接口的方法上分析可以了解到IoService的主要功能: 
1、获取链接通信的元数据 
2、IoService维护一个IoServiceListener的列表,IoServiceListener顾名思义,就是对IoService相关的事件进行监听。 
3、关闭链接 
4、一个IoService对应有一个IoHandler 
5、IoService维护这一个IoSession的map 
6、一个IoService对应一个FilterChain 
7、支持广播功能 
8、管理IoSession的中的数据结构 
9、统计功能 

IoAcceptor    在IoService基础上扩展了绑定和解绑SocketAddress的功能。 
SocketAcceptor    在IoAcceptor的基础上将SocketAddress 具体化到InetSocketAddress,同时将IoSessionConfig具体化到SocketSessionConfig。提供了reuseaddress 和backlog的设置。关于backlog在SocketServer中的文档描述是 
引用

backlog requested maximum length of the queue of incoming connections. 


抽象类分析: 
AbstractIoService 提供了IoService中的一些默认实现。 
Java代码  收藏代码
  1. protected AbstractIoService(IoSessionConfig sessionConfig, Executor executor) {  
  2.     if (sessionConfig == null) {  
  3.         throw new IllegalArgumentException("sessionConfig");  
  4.     }  
  5.   
  6.     if (getTransportMetadata() == null) {  
  7.         throw new IllegalArgumentException("TransportMetadata");  
  8.     }  
  9.   
  10.     if (!getTransportMetadata().getSessionConfigType().isAssignableFrom(  
  11.             sessionConfig.getClass())) {  
  12.         throw new IllegalArgumentException("sessionConfig type: "  
  13.                 + sessionConfig.getClass() + " (expected: "  
  14.                 + getTransportMetadata().getSessionConfigType() + ")");  
  15.     }  
  16.   
  17.     listeners = new IoServiceListenerSupport(this);  
  18.     listeners.add(serviceActivationListener);  
  19.   
  20.     this.sessionConfig = sessionConfig;  
  21.   
  22.     ExceptionMonitor.getInstance();  
  23.   
  24.     if (executor == null) {  
  25.         this.executor = Executors.newCachedThreadPool();  
  26.         createdExecutor = true;  
  27.     } else {  
  28.         this.executor = executor;  
  29.         createdExecutor = false;  
  30.     }  
  31.   
  32.     threadName = getClass().getSimpleName() + '-' + id.incrementAndGet();  
  33. }  

从AbstractIoService 构造函数来分析可以得知 
1、AbstractIoService中只定义了上面的构成函数,没有显式定义无参构造函数,所以在子类的初始化在肯定会调用super(IoSessionConifg,Executor),再从上面构造函数前面的判断来看,IoSessionConfig,TransportMetadata都是由子类构造函数传入。Executor 参数子类可传可不传,不传默认Executors.newCachedThreadPool();创建。 
2、IoServiceListener 列表的管理交给了IoServiceListenerSupport去处理。并添加了一个IoService激活事件的监听器。 
3、创建了一个ExceptionMonitor实例 
4、定义了构造Acceptor处理线程名称的逻辑 

构造函数之外,AbstractIoService 也定义了一些默认实现 
1、IoFilterChain 默认交给DefaultIoFilterChainBuilder 创建 
2、IoSessionDataStructureFactory 默认实现为 DefaultIoSessionDataStructureFactory 
3、实现了dispose的基本逻辑,为什么说是基本逻辑呢?因为dispose调用的 dispose0方法是交由子类去实现的 
Java代码  收藏代码
  1. public final void dispose(boolean awaitTermination) {  
  2.   if (disposed) {  
  3.       return;  
  4.   }  
  5.   
  6.   synchronized (disposalLock) {  
  7.       if (!disposing) {  
  8.           disposing = true;  
  9.   
  10.           try {  
  11.               dispose0();  
  12.           } catch (Exception e) {  
  13.               ExceptionMonitor.getInstance().exceptionCaught(e);  
  14.           }  
  15.       }  
  16.   }  
  17.   
  18.   if (createdExecutor) {  
  19.       ExecutorService e = (ExecutorService) executor;  
  20.       e.shutdownNow();  
  21.       if (awaitTermination) {  
  22.   
  23.         //Thread.currentThread().setName();  
  24.   
  25.         try {  
  26.           LOGGER.debug("awaitTermination on {} called by thread=[{}]"this, Thread.currentThread().getName());  
  27.           e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);  
  28.           LOGGER.debug("awaitTermination on {} finished"this);  
  29.         } catch (InterruptedException e1) {  
  30.           LOGGER.warn("awaitTermination on [{}] was interrupted"this);  
  31.           // Restore the interrupted status  
  32.           Thread.currentThread().interrupt();  
  33.         }  
  34.       }  
  35.   }  
  36.   disposed = true;  
  37. }  

4、实现了broadcast 
Java代码  收藏代码
  1. public final Set<WriteFuture> broadcast(Object message) {  
  2.     // Convert to Set.  We do not return a List here because only the  
  3.     // direct caller of MessageBroadcaster knows the order of write  
  4.     // operations.  
  5.     final List<WriteFuture> futures = IoUtil.broadcast(message,  
  6.             getManagedSessions().values());  
  7.     return new AbstractSet<WriteFuture>() {  
  8.         @Override  
  9.         public Iterator<WriteFuture> iterator() {  
  10.             return futures.iterator();  
  11.         }  
  12.   
  13.         @Override  
  14.         public int size() {  
  15.             return futures.size();  
  16.         }  
  17.     };  
  18. }  


AbstractIoAcceptor  继承自AbstractIoService并实现了IoAcceptor接口,主要的实现有: 
1、增加一个可配置的SocketAddress 列表 defaultLocalAddresses ,以及这个列表的只读版本 
2、增加一个已绑定的SocketAddress 列表 
3、增加一个disconnectOnUnbind 配置,指定在Unbind时是否断掉与客户端的链接 
4、实现了bind的基本逻辑,更具体的逻辑在bindInternal中交由子类去实现 
Java代码  收藏代码
  1. public final void bind(Iterable<? extends SocketAddress> localAddresses) throws IOException {  
  2.     if (isDisposing()) {  
  3.         throw new IllegalStateException("Already disposed.");  
  4.     }  
  5.       
  6.     if (localAddresses == null) {  
  7.         throw new IllegalArgumentException("localAddresses");  
  8.     }  
  9.       
  10.     List<SocketAddress> localAddressesCopy = new ArrayList<SocketAddress>();  
  11.       
  12.     for (SocketAddress a: localAddresses) {  
  13.         checkAddressType(a);  
  14.         localAddressesCopy.add(a);  
  15.     }  
  16.       
  17.     if (localAddressesCopy.isEmpty()) {  
  18.         throw new IllegalArgumentException("localAddresses is empty.");  
  19.     }  
  20.       
  21.     boolean activate = false;  
  22.     synchronized (bindLock) {  
  23.         synchronized (boundAddresses) {  
  24.             if (boundAddresses.isEmpty()) {  
  25.                 activate = true;  
  26.             }  
  27.         }  
  28.   
  29.         if (getHandler() == null) {  
  30.             throw new IllegalStateException("handler is not set.");  
  31.         }  
  32.           
  33.         try {  
  34.             Set<SocketAddress> addresses = bindInternal( localAddressesCopy );  
  35.               
  36.             synchronized (boundAddresses) {  
  37.                 boundAddresses.addAll(addresses);  
  38.             }  
  39.         } catch (IOException e) {  
  40.             throw e;  
  41.         } catch (RuntimeException e) {  
  42.             throw e;  
  43.         } catch (Throwable e) {  
  44.             throw new RuntimeIoException(  
  45.                     "Failed to bind to: " + getLocalAddresses(), e);  
  46.         }  
  47.     }  
  48.       
  49.     if (activate) {  
  50.         getListeners().fireServiceActivated();  
  51.     }  
  52. }  

5、实现了unbind的基本逻辑,更具体的逻辑在unbind0中交由子类实现 
Java代码  收藏代码
  1. public final void unbind(Iterable<? extends SocketAddress> localAddresses) {  
  2.     if (localAddresses == null) {  
  3.         throw new IllegalArgumentException("localAddresses");  
  4.     }  
  5.       
  6.     boolean deactivate = false;  
  7.     synchronized (bindLock) {  
  8.         synchronized (boundAddresses) {  
  9.             if (boundAddresses.isEmpty()) {  
  10.                 return;  
  11.             }  
  12.   
  13.             List<SocketAddress> localAddressesCopy = new ArrayList<SocketAddress>();  
  14.             int specifiedAddressCount = 0;  
  15.               
  16.             for (SocketAddress a: localAddresses ) {  
  17.                 specifiedAddressCount++;  
  18.   
  19.                 if ((a != null) && boundAddresses.contains(a) ) {  
  20.                     localAddressesCopy.add(a);  
  21.                 }  
  22.             }  
  23.               
  24.             if (specifiedAddressCount == 0) {  
  25.                 throw new IllegalArgumentException( "localAddresses is empty." );  
  26.             }  
  27.               
  28.             if (!localAddressesCopy.isEmpty()) {  
  29.                 try {  
  30.                     unbind0(localAddressesCopy);  
  31.                 } catch (RuntimeException e) {  
  32.                     throw e;  
  33.                 } catch (Throwable e) {  
  34.                     throw new RuntimeIoException(  
  35.                             "Failed to unbind from: " + getLocalAddresses(), e );  
  36.                 }  
  37.   
  38.                 boundAddresses.removeAll(localAddressesCopy);  
  39.                   
  40.                 if (boundAddresses.isEmpty()) {  
  41.                     deactivate = true;  
  42.                 }  
  43.             }  
  44.         }  
  45.     }  
  46.   
  47.     if (deactivate) {  
  48.         getListeners().fireServiceDeactivated();  
  49.     }  
  50. }  


AbstractPollingIoAcceptor<T extends AbstractIoSession, H> 
泛参H在子类NioSocketAcceptor中替换为ServerSocketChannel,泛参T替换为NioSession。这样便于分析后面的代码。 
主要实现了bind,accept,dispose ServerSocket的基本逻辑。父类AbstractIoService中的Executor主要用于执行ServerSocket的accept逻辑。一旦与客户端建立连接后,之后的I/O操作将交由IoProcessor去处理。关于ServerSocketChannel 的 select,open,close,accept都交由子类实现 

私有构造函数定义了IoProcessor实例由外部注入,并初始化seelectable标记为true。具体的init()逻辑由子类去实现。 
Java代码  收藏代码
  1. private AbstractPollingIoAcceptor(IoSessionConfig sessionConfig,  
  2.         Executor executor, IoProcessor<NioSession> processor,  
  3.         boolean createdProcessor) {  
  4.     super(sessionConfig, executor);  
  5.   
  6.     if (processor == null) {  
  7.         throw new IllegalArgumentException("processor");  
  8.     }  
  9.     //注入IoProcessor对象  
  10.     this.processor = processor;  
  11.     this.createdProcessor = createdProcessor;  
  12.   
  13.     try {  
  14.         //初始化设置交给子类实现  
  15.         init();  
  16.         // 构造函数中设置标记为true,后面便可以s  
  17.         selectable = true;  
  18.     } catch (RuntimeException e) {  
  19.         throw e;  
  20.     } catch (Exception e) {  
  21.         throw new RuntimeIoException("Failed to initialize.", e);  
  22.     } finally {  
  23.         if (!selectable) {  
  24.             try {  
  25.                 destroy();  
  26.             } catch (Exception e) {  
  27.                 ExceptionMonitor.getInstance().exceptionCaught(e);  
  28.             }  
  29.         }  
  30.     }  
  31. }  

其他几个重载的构造函数注入默认IoProcessor为SimpleIoProcessorPool实例 
Java代码  收藏代码
  1. protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig,  
  2.         Class<? extends IoProcessor<T>> processorClass, int processorCount) {  
  3.     this(sessionConfig, nullnew SimpleIoProcessorPool<T>(processorClass,  
  4.             processorCount), true);  
  5. }  

提供了一个轮询策略的Acceptor的实现 
Java代码  收藏代码
  1. private class Acceptor implements Runnable {  
  2.     public void run() {  
  3.         // nHandles 表示已经open的ServerSocketChannel数量  
  4.         int nHandles = 0;  
  5.         //无限循环,接收客户端的链接请求,并处理,直到所有opened ServerSocketChannel都被close  
  6.         while (selectable) {  
  7.             try {  
  8.                 //轮询获得  
  9.                 int selected = select();  
  10.                 //open ServerSocketChannel并增加nHandles  
  11.                 nHandles += registerHandles();  
  12.   
  13.                 if (selected > 0) {  
  14.                     // We have some connection request, let's process   
  15.                     // them here.   
  16.                     processHandles(selectedHandles());  
  17.                 }  
  18.   
  19.                 //close ServerSocketChannel并减少nHandles  
  20.                 nHandles -= unregisterHandles();  
  21.                 //没有ServerSocketChannel在监听客户端的请求,跳出循环  
  22.                 if (nHandles == 0) {  
  23.                     synchronized (lock) {  
  24.                         if (registerQueue.isEmpty()  
  25.                                 && cancelQueue.isEmpty()) {  
  26.                             acceptor = null;  
  27.                             break;  
  28.                         }  
  29.                     }  
  30.                 }  
  31.             } catch (ClosedSelectorException cse) {  
  32.                 break;  
  33.             } catch (Throwable e) {  
  34.                 ExceptionMonitor.getInstance().exceptionCaught(e);  
  35.   
  36.                 try {  
  37.                     Thread.sleep(1000);  
  38.                 } catch (InterruptedException e1) {  
  39.                     ExceptionMonitor.getInstance().exceptionCaught(e1);  
  40.                 }  
  41.             }  
  42.         }  
  43.   
  44.         if (selectable && isDisposing()) {  
  45.             selectable = false;  
  46.             try {  
  47.                 if (createdProcessor) {  
  48.                     processor.dispose();  
  49.                 }  
  50.             } finally {  
  51.                 try {  
  52.                     synchronized (disposalLock) {  
  53.                         if (isDisposing()) {  
  54.                             destroy();  
  55.                         }  
  56.                     }  
  57.                 } catch (Exception e) {  
  58.                     ExceptionMonitor.getInstance().exceptionCaught(e);  
  59.                 } finally {  
  60.                     disposalFuture.setDone();  
  61.                 }  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     private void processHandles(Iterator<ServerSocketChannel> handles) throws Exception {  
  67.         while (handles.hasNext()) {  
  68.             ServerSocketChannel handle = handles.next();  
  69.             handles.remove();  
  70.             // 接收客户端的请求,建立链接,返回对链接信息封装后的IoSession  
  71.             NioSession session = accept(processor, handle);  
  72.               
  73.             if (session == null) {  
  74.                 break;  
  75.             }  
  76.             // 初始化IoSession信息  
  77.             initSession(session, nullnull);  
  78.             // 将连接的I/O(read,write,close etc)交给Processor线程处理  
  79.             session.getProcessor().add(session);  
  80.         }  
  81.     }  
  82. }  
  83.   
  84. private int registerHandles() {  
  85.     //开启一个无限循环,不断从registerQueue队列中获取AcceptorOperationFuture,直到registerQueue为空  
  86.     for (;;) {  
  87.         AcceptorOperationFuture future = registerQueue.poll();  
  88.           
  89.         if (future == null) {  
  90.             return 0;  
  91.         }  
  92.   
  93.         // 创建一个临时的map以便在打开socket的时候出现异常及时释放资源  
  94.         Map<SocketAddress, ServerSocketChannel> newHandles = new ConcurrentHashMap<SocketAddress, ServerSocketChannel>();  
  95.         List<SocketAddress> localAddresses = future.getLocalAddresses();  
  96.   
  97.         try {  
  98.             for (SocketAddress a : localAddresses) {  
  99.                 //遍历所有的SocketAddress,open ServerSocketChannel  
  100.                 ServerSocketChannel handle = open(a);  
  101.                 newHandles.put(localAddress(handle), handle);  
  102.             }  
  103.             // 未出现异常,将所有open成功的ServerSocketChannel放到boundHandles  
  104.             boundHandles.putAll(newHandles);  
  105.             // 设置异步处理完成  
  106.             future.setDone();  
  107.             // 返回open成功的ServerSocketChannel的数量  
  108.             return newHandles.size();  
  109.         } catch (Exception e) {  
  110.             future.setException(e);  
  111.         } finally {  
  112.             //在open时出现了异常,释放相应的 资源  
  113.             if (future.getException() != null) {  
  114.                 for (ServerSocketChannel handle : newHandles.values()) {  
  115.                     try {  
  116.                         close(handle);  
  117.                     } catch (Exception e) {  
  118.                         ExceptionMonitor.getInstance().exceptionCaught(e);  
  119.                     }  
  120.                 }  
  121.                   
  122.                 wakeup();  
  123.             }  
  124.         }  
  125.     }  
  126. }  
  127.   
  128. // 关闭ServerSocketChannel  
  129. private int unregisterHandles() {  
  130.     int cancelledHandles = 0;  
  131.     // 循环从cancelQueue队列中获取待关闭的ServerSocketChannel,直到cancelQueue清空  
  132.     for (;;) {  
  133.         AcceptorOperationFuture future = cancelQueue.poll();  
  134.         if (future == null) {  
  135.             break;  
  136.         }  
  137.   
  138.         for (SocketAddress a : future.getLocalAddresses()) {  
  139.             // 先从已绑定的ServerSocketChannel列表中移除  
  140.             ServerSocketChannel handle = boundHandles.remove(a);  
  141.               
  142.             if (handle == null) {  
  143.                 continue;  
  144.             }  
  145.   
  146.             try {  
  147.                 //关闭ServerSocketChannel,真正的实现交给子类  
  148.                 close(handle);  
  149.                 wakeup();  
  150.             } catch (Throwable e) {  
  151.                 ExceptionMonitor.getInstance().exceptionCaught(e);  
  152.             } finally {  
  153.                 cancelledHandles++;  
  154.             }  
  155.         }  
  156.         //  
  157.         future.setDone();  
  158.     }  
  159.     //返回已关闭的ServerSocketChannel的数量   
  160.     return cancelledHandles;  
  161. }  


NioSocketAcceptor 
基于tcp协议的java nio版IoAcceptor实现,到这里已经实现所有的网络I/O操作。 
Java代码  收藏代码
  1. //默认的ServerSocket的backlog属性为50  
  2. private int backlog = 50;  
  3. // 默认reuseAddress为false  
  4. private boolean reuseAddress = false;  
  5. // java nio 中的selector,状态改变多线程可见  
  6. private volatile Selector selector;  
  7.   
  8. //构造函数出入的默认IoSessionConfig实现为DefaultSocketSessionConfig  
  9. public NioSocketAcceptor() {  
  10.     super(new DefaultSocketSessionConfig(), NioProcessor.class);  
  11.     ((DefaultSocketSessionConfig) getSessionConfig()).init(this);  
  12. }  
  13. // 如果你熟悉java nio,看到这些代码是否有种豁然开朗的感觉呢?原来是这样的啊!  
  14. @Override  
  15. protected void init() throws Exception {  
  16.     selector = Selector.open();  
  17. }  
  18.   
  19. @Override  
  20. protected void destroy() throws Exception {  
  21.     if (selector != null) {  
  22.         selector.close();  
  23.     }  
  24. }  
  25.   
  26. public TransportMetadata getTransportMetadata() {  
  27.     return NioSocketSession.METADATA;  
  28. }  
  29.   
  30. @Override  
  31. protected NioSession accept(IoProcessor<NioSession> processor,  
  32.         ServerSocketChannel handle) throws Exception {  
  33.   
  34.     SelectionKey key = handle.keyFor(selector);  
  35.       
  36.     if ((key == null) || (!key.isValid()) || (!key.isAcceptable()) ) {  
  37.         return null;  
  38.     }  
  39.   
  40.     SocketChannel ch = handle.accept();  
  41.       
  42.     if (ch == null) {  
  43.         return null;  
  44.     }  
  45.   
  46.     return new NioSocketSession(this, processor, ch);  
  47. }  
  48.   
  49. @Override  
  50. protected ServerSocketChannel open(SocketAddress localAddress)  
  51.         throws Exception {  
  52.     // Creates the listening ServerSocket  
  53.     ServerSocketChannel channel = ServerSocketChannel.open();  
  54.       
  55.     boolean success = false;  
  56.       
  57.     try {  
  58.         // This is a non blocking socket channel  
  59.         channel.configureBlocking(false);  
  60.       
  61.         // Configure the server socket,  
  62.         ServerSocket socket = channel.socket();  
  63.           
  64.         // Set the reuseAddress flag accordingly with the setting  
  65.         socket.setReuseAddress(isReuseAddress());  
  66.           
  67.         // and bind.  
  68.         socket.bind(localAddress, getBacklog());  
  69.           
  70.         // Register the channel within the selector for ACCEPT event  
  71.         channel.register(selector, SelectionKey.OP_ACCEPT);  
  72.         success = true;  
  73.     } finally {  
  74.         if (!success) {  
  75.             close(channel);  
  76.         }  
  77.     }  
  78.     return channel;  
  79. }  
  80.   
  81. @Override  
  82. protected void close(ServerSocketChannel handle) throws Exception {  
  83.     SelectionKey key = handle.keyFor(selector);  
  84.       
  85.     if (key != null) {  
  86.         key.cancel();  
  87.     }  
  88.       
  89.     handle.close();  
  90. }  
  91.   
  92. @Override  
  93. protected void wakeup() {  
  94.     selector.wakeup();  
  95. }  http://berdy.iteye.com/blog/1960639
  96. 转自:http://berdy.iteye.com/blog/1960639
0 0