网络编程NIO-异步

异步I/O是没有阻塞地读写数据的方法。通常在代码进行read调用时,代码会阻塞直至可供读取的数据。同样,write调用将会阻塞直至数据能够写入。

 

1、selector是一个对象,可以注册到很多个channel上,监听各个channel上发生的事件,并且能够根据事件情况决定channel读写,这样通过一个线程管理多个channel

创建selector:

Selector selector = Selector.open();

注册channel到selector:

channel.configureBlocking(false);

SelectionKey key = chanenl.register(selector, SelecltionKey.OP_READ_;

注意,注册channel必须设置为异步模式才可以。register调用的返回值是selectionKey。这个对象待办这个通道在此selector上的这个注册。当某个selector

通知你某个传入事件时,它是通过提高对应于该事件的SelectionKey来进行的。selectionKey还可以用于取消通过的注册

 

2、channel和selector

Channel channel = selectionKey.channel();

Selector selector = selectioKey.selector();

 

demo:

public class MultiPortEcho {

  private int ports[];

  private ByteBuffer echoBuffer = ByteBuffer.allocate(1024);

  public MultiPortEcho(int ports[]) throws IOException {

  this.ports = ports;

  go();

}

private void go() throws IOException {

  //create selector

  Selector selector = Selector.open();

  //为每个端口打开一个监听,并把这些监听注册到selector中

  for(int i = 0; i < ports.length; ++i) {

    //打开一个serverSocketChannel

    ServerSocketChannel ssc = ServerSocketChnanel.open();

    ssc.configureBlocking(false);//设置为非阻塞

    ServerSocket ss = ssc.socket();

    InetSocketAddress address = new InetSocketAddress(ports[i]);

    ss.bind(address); //监听一个端口

    //注册到selector

    SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);

    System.out.println("going to listen to " + ports[i]);

  }

  while(true) {

    int num = selector.select();//返回所发生的事件的数量

    Set selectedKeys = selector.selectKeys();

    Iterator it = selectedKeys.iterator();

    while(it.hasNext()) {

      SelectionKey key = (SelectionKey)it.next();

      //监听新连接,调用readops方法,检查发生了什么类型的事件

      if((key.readyOps() & selectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {

        //接受一个新连接

        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

        SocketChannel sc = ssc.accept();

        sc.configureBlocking(false);

        //将新连接注册到selector。

        SelectionKey newKey = sc.register(selector, SelectionKey.OP_READ);

        it.remove();

        System.out.println("got connection from " + sc);

      }else if( (key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {

          SocketChannel sc = (SocketChannel)key.channel();

          int bytesEchoed = 0;

          while(true) {

            echoBuffer.clear();

            int r = sc.read(echoBuffer);

            if( r <= 0 ) {

            break;

          }

          echoBuffer.flip();

          sc.write(echoBuffer);

          bytesEchoed += r;

        }

        System.out.println("echoed" + bytesEchoed + "from" + sc);

        it.remove();

        // System.out.println( "going to clear" ); // selectedKeys.clear(); // System.out.println( "cleared" );

      }

    }

    static public void main(String args2[]) throws Exception {

      String args[]={"9001","9002","9003"};

       if (args.length <= 0) {

        System.err.println("Usage: java MultiPortEcho port [port port ...]");

        System.exit(1);

       }

      int ports[] = new int[args.length];

      for (int i = 0; i < args.length; ++i) {

        ports[i] = Integer.parseInt(args[i]);

      }

      new MultiPortEcho(ports);

    }

  }

  }

}

posted @ 2018-01-27 21:07  秋水秋色  阅读(498)  评论(0编辑  收藏  举报