/**
  * 有通道可读, 调用Session的onRead, 把数据读到Session的私有输入缓冲
  *
  * @param key
  * @throws IOException
  * @throws InterruptedException
  */
 private void onRead(SelectionKey key) throws IOException {
   Session session = (Session) key.attachment();
   try {
     session.onRead();
   } catch (InterruptedException e) {
     logger.error("OOPS Exception:", e);
     Thread.currentThread().interrupt();
   }
 }
 /**
  * 有客户端连接可以接收, 分配Session, 启动Session, 这个Session专门负责处理这个客户端的所有请求
  *
  * @param key
  * @throws IOException
  */
 private void onAccept(SelectionKey key) throws IOException {
   SocketChannel channel = ((ServerSocketChannel) key.channel()).accept();
   opsChangeRequstMap.put(channel, new SocketChannelOPSChangeRequest(channel, 0));
   if (logger.isWarnEnabled())
     logger.warn("Accept client from : " + channel.socket().getRemoteSocketAddress());
   channel.configureBlocking(false);
   Session session = sessionManager.newSession(this, channel, false);
   channel.register(selector, SelectionKey.OP_READ, session);
   session.start();
 }
  private void dispatch() throws IOException {
    SelectionKey key = null;
    for (SocketChannelOPSChangeRequest request : opsChangeRequstMap.values()) {
      key = request.getChannel().keyFor(selector);
      if (key != null) {
        // 写优先
        if ((request.getOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) {
          key.interestOps(SelectionKey.OP_WRITE);
          request.clearOps(SelectionKey.OP_WRITE);
        } else if ((request.getOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
          key.interestOps(SelectionKey.OP_READ);
          request.clearOps(SelectionKey.OP_READ);
        }
      }
    }

    isWeakuped.set(false);
    if (selector.select(WaveriderConfig.WAVERIDER_DEFAULT_NETWORK_TIME_OUT) <= 0) {
      return;
    }

    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
    while (iterator.hasNext()) {
      key = (SelectionKey) iterator.next();
      iterator.remove();
      try {
        if (!key.isValid()) {
          continue;
        } else if (key.isAcceptable()) {
          onAccept(key);
        } else if (key.isReadable()) {
          // readerExecutor.execute(new NetworkTask(key, NETWORK_OPERATION_READ));
          onRead(key);
        } else if (key.isWritable()) {
          // writerExecutor.execute(new NetworkTask(key, NETWORK_OPERATION_WRITE));
          onWrite(key);
        }
      } catch (IOException e) {
        // 客户端连接出问题
        Session session = (Session) key.attachment();
        if (session != null) {
          session.onException();
          // 释放Session
          sessionManager.freeSession(session);
        }
        opsChangeRequstMap.remove((SocketChannel) key.channel());
        key.cancel();
        key.channel().close();
        e.printStackTrace();
        logger.error("OOPS:Exception:", e);
      }
    }
  }
 @Override
 public void run() {
   try {
     switch (operation) {
       case NETWORK_OPERATION_ACCEPT:
         {
           onAccept(key);
           break;
         }
       case NETWORK_OPERATION_READ:
         {
           onRead(key);
           break;
         }
       case NETWORK_OPERATION_WRITE:
         {
           onWrite(key);
           break;
         }
     }
   } catch (IOException e) {
     logger.error("OOPS:Exception:", e);
     try {
       // 客户端连接出问题
       Session session = (Session) key.attachment();
       if (session != null) {
         session.onException();
         // 释放Session
         sessionManager.freeSession(session);
       }
       opsChangeRequstMap.remove((SocketChannel) key.channel());
       key.cancel();
       key.channel().close();
     } catch (IOException ex) {
       logger.error("OOPS:Exception:", ex);
       ex.printStackTrace();
     }
   }
 }
 /**
  * 有通道可写, 调用Session的onWrite, 把Session的私有输出缓冲中数据写到网络
  *
  * @param key
  * @throws IOException
  */
 private void onWrite(SelectionKey key) throws IOException {
   key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
   Session session = (Session) key.attachment();
   session.onWrite();
   // key.interestOps(SelectionKey.OP_READ);
 }