content: package com.lgp.netty.netty_ch2;
  
  import java.io.IOException;
  import java.net.InetSocketAddress;
  import java.net.ServerSocket;
  import java.nio.ByteBuffer;
  import java.nio.channels.SelectionKey;
  import java.nio.channels.Selector;
  import java.nio.channels.ServerSocketChannel;
  import java.nio.channels.SocketChannel;
  import java.util.Iterator;
  import java.util.Set;
  
  /**
   * @AUTHOR lgp
   * @DESCRIPTION
   **/
  public class PlainNioServer {
      public void serve(int port) throws IOException {
          ServerSocketChannel serverChannel = ServerSocketChannel.open();
          serverChannel.configureBlocking(false);
  
          ServerSocket ss = serverChannel.socket();
          InetSocketAddress address = new InetSocketAddress(port);
  //      1  绑定服务器到制定端口
          ss.bind(address);
  //      2  打开 selector 处理 channel
          Selector selector = Selector.open();
          //3 将selector注册到serverChannel
          serverChannel.register(selector, SelectionKey.OP_ACCEPT);
          final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes());
          for (; ; ) {
              try {
  //               4 等待新的事件来处理。这将阻塞，直到一个事件是传入。
                  selector.select();
              } catch (IOException ex) {
                  ex.printStackTrace();
                  break;
              }
              //5 从收到的所有事件中 获取 SelectionKey 实例。
              Set<SelectionKey> readyKeys = selector.selectedKeys();
              Iterator<SelectionKey> iterator = readyKeys.iterator();
              while (iterator.hasNext()) {
                  SelectionKey key = iterator.next();
                  iterator.remove();
                  try {
                      //6 检查该事件是一个新事件
                      if (key.isAcceptable()) {
                          ServerSocketChannel server = (ServerSocketChannel) key.channel();
  //                        7 得到客户端连接
                          SocketChannel client = server.accept();
                          client.configureBlocking(false);
                          //8 将selector注册进client
                          client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate());
                          System.out.println("Accepted connection from " + client);
                      }
                      //9 检查socket是否准备好写数据
                      if (key.isWritable()) {
                          SocketChannel client = (SocketChannel) key.channel();
                          ByteBuffer buffer = (ByteBuffer) key.attachment();
  //                        10 将数据写入到所连接的客户端。如果网络饱和，连接是可写的，那么这个循环将写入数据，直到该缓冲区是空的。
                          while (buffer.hasRemaining()) {
                              if (client.write(buffer) == 0) {
                                  break;
                              }
                          }
                          //10 关闭连接
                          client.close();
                      }
                  } catch (IOException ex) {
                      key.cancel();
                      try {
                          key.channel().close();
                      } catch (IOException cex) {
                          // 在关闭时忽略
                      }
                  }
              }
          }
      }
  }
  