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 } buffer.flip();28 } it.remove();30 } } } }
上面這段程式碼是書上關於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具體工作流程範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!