首页 > 代码库 > Nio经典工作方式

Nio经典工作方式

 1 public void selector() throws IOException {
 2     ByteBuffer buffer = ByteBuffer.allocate(1024);
 3     Selector selector = Selector.open();
 4     ServerSocketChannel ssc = ServerSocketChannel.open();
 5     ssc.configureBlocking(false);//设置为非阻塞模式
 6     ssc.socket().bind(new InetSocketAddress(8080));
 7     ssc.register(selector, SelectionKey.OP_ACCEPT);//注册监听事件
 8     while(true) {
 9         Set selectorKeys = selector.selectorKeys();//取得所有key的集合
10         Iterator it = selectorKeys.iterator();
11         while(it.hasNext()) { //检查序列是否还有元素
12             SelectionKey key = (SelectionKey) it.next();
13             if((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
14                 ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
15                 SocketChannel sc = ssChannel.accept();//接受到服务端的请求
16                 sc.configureBlocking(false);
17                 sc.register(selector,SelectionKey.OP_ACCEPT);
18                 it.remove();
19             } else if((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
20                 SocketChannel sc = (SocketChannel) key.channel;
21                 while(true) {
22                     buffer.clear();
23                     int n = sc.read(buffer);//读取数据
24                     if(n <= 0) {
25                         break;
26                     }
27                     buffer.flip();
28                 }
29                 it.remove();
30             }
31             
32         }
33         
34     }
35     
36 }

  上面这段代码是书上关于Nio具体工作过程的代码示例。其工作过程可以具体阐述如下:

中有两个关键的类:Channel和Selector,它们是NIO中的核心概念。其中Channel可类比为交通工具,而且是具体的交通工具,例如:汽车,自行车。而Selector则可以类比为车辆调度系统,负责车辆运行状况的监视和具体调度工作。

ServerSocketChannel类是针对面向流的侦听套接字的可选择通道,在服务端创建完此类实例后通过Socket()方法(获取与此通道关联的服务器套接字)返回一个ServerSocket类的实例,在利用此实例的void bind(SocketAddress endpoint)方法将 ServerSocket 绑定到特定地址(IP 地址和端口号)。就像出租车公司的每辆出租车都要在公司注册一样,我们也需要将ServerSocketChannel的实例通过register()方法将此通道注册到指定的选择器。

后调用Selector的selectedKeys方法来检查已经注册在这个选择器上的所有通信信道是否有需要的事件发生,如果有某个事件发生,将会返回所有的SelectionKey,由于key.readyOps()获取此键的 ready 操作集合,所以个人认为key.readyOps()&SelectionKey.OP_ACCEPT意思是此键的 ready 操作集合为ACCEPT状态,即服务器处于监听状态,通过这个对象的Channel方法就可以取得这个通信信道对象,然后调用accept()方法返回一个套接字通道,默认为阻塞状态,也可以利用Channel方法取得的通信信道对象读取通信的数据,而这里读取的数据是Buffer,这个Buffer是我们可以控制的缓冲器。


Nio经典工作方式