成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java NIO 深入研究

開發 后端
本文主要針對Java NIO一些概念進行深入研究。

No-Block 和Block IO 的區別:

一個典型的網絡通訊步驟為: open (新建socket Chanel )--> connect( 嘗試建立連接) --> accept( 連接被接受) --> read( 讀取請求)send (輸出結果)--> close( 連接關閉) 。

對于一個No-Block 的網絡IO ,上面的每一步都是會馬上返回的,當然返回的結果可能為null ,可能不為null ,這個要看下上文(context )決定。一般情況下,我們都是需要不為null 的結果,這個就需要我們在適當的時機,執行適當的步驟,這樣就會得到我們想要的結果。何為適當的時機?這個下面會講。

對于一個block 的網絡IO ,上面的每一步執行的時候,如果沒到適當的時機,當前線程就會被block 住,直到適當的時機,返回給你確定的結果。

當然對與No-Block 或者Block IO ,上面的每一步都有可能會拋出IOException 異常的。

NIO 編程接觸的幾個關鍵概念:

Buffer :是一塊連續的內存塊,是 NIO 數據讀或寫的中轉地。Buffer 這篇blog 暫時略過不講。

Chanel :數據的源頭或者數據的目的地,用于向 buffer 提供數據或者讀取 buffer 數據 ,異步 I/O 支持。

注意chanel 有2 類,一種叫SocketChanel, 一種叫ServerSocketChanel ,看名字我們就知道,一類是普通的socket chanel ,client 端和服務器端都用的,一類是專門用在server 端的。當然這個界限也不是絕對的,互為client 和server 的情況也是存在的。

Selector : chanel 事件的偵聽者, 它能檢測一個或多個通道 (channel) 上的事件,并將事件分發出去。使用一個 select 線程就能監聽多個通道上的事件,并基于事件驅動觸發相應的響應。

SelectionKey : chanel 上發生的事件, 包含了事件的狀態信息和時間以及對應的 chanel 。

Chanel 的狀態:

可連( Connectable ):當一個 Chanel 完成 socket 連接操作已完成或者已失敗放棄時。

能連( Acceptable ):當一個 Chanel 已經準備好接受一個新的 socket 連接時。

可讀( Readable ):當一個 Chanel 能被讀時。

可寫( Writable ):當一個 Chanel 能被寫時。

 

結合對照上面的網絡通訊步驟我們可以有以下推導出的結論:

當一個 Server Chanel 是 Connectable 時, client 端嘗試 connect 才會成功。

當一個 Server Chanel 是 Acceptable 時, client 的連接請求被真正受理,一個新的 chanel 會被生成,并且記錄了 localAdrress 和 remoteAddress. 為進一步讀寫做準備。

當一個 Chanel 是 Readable 時,我們從這個 Chanel 中讀取數據才會成功。

當一個 Chanel 是 Writable 時,我們往這個 Chanel 中寫數據才會成功。

記住一點,對于一個 No-Block 的 Chanel 來說,上面 4 個操作都會馬上返回或者拋出 IOException ,但是是不是成功就難說了,前面就說了,我們在一個 Chanel 做操作的時候,我們要密切關注 Chanel 的當前狀態。只有在知道 Chanel 的當前狀態時,我們才能在這個 Chanel 上做最適當的操作。

聰明的你可能馬上就會想到,要是你操作的 Chanel 的狀態的轉換信息能被你抓取,這些問題就迎刃而解了。對啦, NIO 就是這樣設計的。一個 Chanel 可以注冊一個 Selector (就像一個事件偵聽器),而且你還要告知你想要要偵聽的狀態。用一段代碼來說明下:

  1. selector = SelectorProvider.provider().openSelector();  
  2. serverChannel1 = ServerSocketChannel.open();  
  3. serverChannel1.configureBlocking(false);  
  4. InetSocketAddress isa = new InetSocketAddress("localhost"9999);  
  5. serverChannel1.socket().bind(isa);  
  6. serverChannel1.register(selector, SelectionKey.OP_ACCEPT); 

這段代碼的意思就是我們打開了一個 ServerChanel ,偵聽本機的 9999 端口,并且新建了一個 Selector, 然后這個 ServerChanel 注冊了這個 Selector ,并且指定了它感興趣的狀態類型是 OP_ACCEPT. 這樣有什么效果呢?

注意紅色那句,這句意思是selector要求serverChannel1狀態為acceptable的時候把這個消息告訴selector。

效果就是:

當這個 ServerChanel 狀態為 Acceptable 時, Selector 就會收到一個消息,這個消息當然就是一個 SelectionKey 對象。調用 Selector 的 selectedKeys ()方法,我們就能得到所有 Chanel 發送過來的消息。

因為 SelectionKey 包含 事件的狀態,時間以及對應的 Chanel ,很自然的,我們遍歷這個 Set<SelectionKey>, 根據 SelectionKey 的狀態,就能在相應的 Chanel 做正確的操作。比如,能讀的時候我們就讀,能寫的時候我們就寫。

***講講 Server 端和 Client 編程的一般步驟:

對于 Client 來一般是這樣的:

  1. InetSocketAddress isa = new InetSocketAddress(host, port);   
  2. SocketChannel sc = null;   
  3. sc = SocketChannel.open();   
  4. sc.connect(isa);   
  5. sc.write(data);   
  6. …   
  7. Sc.read(buff);  

構造一個 InetSocketAddress 對象 --> open --> connect --> write --> read

注意這里用的不是 No-Block 的方式,因為 client 如果沒有得到 server 端的正確回應的話就采取下一步操作無疑是沒有意義的。

Server 端:

 

  1. selector = SelectorProvider.provider ().openSelector();   
  2. serverChannel = ServerSocketChannel.open ();   
  3. serverChannel .configureBlocking( false );   
  4. InetSocketAddress isa = new InetSocketAddress( "localhost" , 9999 );   
  5. serverChannel .socket().bind(isa);   
  6. serverChannel .register( selector , SelectionKey. OP_ACCEPT );  

構造一個 Selector --> 打開一個 serverSocketChanel --> 設定 serverSocketChanel 為 no-block-->bind serverSocketChanel 到一個 host 和 port --> register Selector 并告知感興趣的狀態類型轉換。

在 SelectionKey Set 上遍歷操作:

 

 

  1. while (true) {   
  2. selector.select();   
  3. Iterator selectedKeys = this.selector.selectedKeys().iterator();   
  4. while (selectedKeys.hasNext()) {   
  5. SelectionKey key = (SelectionKey) selectedKeys.next();   
  6. selectedKeys.remove();   
  7. if (!key.isValid()) {   
  8. continue;   
  9. }   
  10. if (key.isAcceptable()) {   
  11. accept(key);   
  12. else if (key.isReadable()) {   
  13. read(key);   
  14. else if (key.isWritable()) {   
  15. write(key);   
  16. }   
  17. }   
  18. }  

在這個循環里面我們會根據 SelectionKey 的狀態,采取不同的操作的。當連接被 accepted 時, 一個新的 chanel 會被生成,并且記錄了 localAdrress 和 remoteAddress. 為進一步讀寫做準備。

accept 函數如下:

  1. public void accept(SelectionKey key) throws IOException {   
  2. ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();  
  3. SocketChanel socketChannel1 = serverSocketChannel.accept();   
  4. socketChannel1.configureBlocking(false);   
  5. socketChannel1.register(selector, SelectionKey.OP_READ);   
  6. }  

這里新的 Chanel 被構建,***同樣會注冊到 selector , 同時要求當這個 Chanel 為 Readable 時,一個 SelectionKey 被放入到 Selector 中。這樣上面循環會用 read(key) 來處理這個 SelectionKey。

原文鏈接:http://tangay.iteye.com/blog/848485

 【編輯推薦】

  1. Java數據緩存實現的核心機制
  2. Java NIO TCP編程
  3. Java NIO性能測試
  4. Java NIO 經典實例代碼
  5. Java NIO聊天窗口實例
責任編輯:林師授 來源: tangay的博客
相關推薦

2022-05-11 09:03:05

CSS容器文本換行

2011-06-01 10:58:54

Android Service

2016-01-12 18:04:55

Java異常研究

2017-06-06 11:29:23

Java異常研究與分析

2010-11-18 17:24:27

Oracle旋轉ins

2018-12-24 15:00:58

混合云多云云采用

2010-11-23 16:35:59

MySQL刪除多表數據

2023-11-03 08:25:28

數據結構Java

2010-05-31 17:45:50

MySQL行鎖

2010-11-26 11:57:35

MySQL結果字符串

2022-04-19 08:28:34

main函數

2009-10-20 10:17:50

綜合布線系統驗收

2010-06-21 13:07:14

2016-03-02 15:09:57

Java虛擬機體系結構

2010-05-19 14:45:46

2009-11-11 13:49:02

路由器技術

2021-05-25 09:00:00

Kubernetes容器集群

2009-12-08 18:45:17

PHP檢查函數可用

2013-01-07 13:38:56

Android開發布局長度單位

2012-01-18 11:24:18

Java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本精品视频 | 久久久久国产一区二区三区四区 | 亚洲福利网 | 精品一区二区三区在线观看国产 | www精品美女久久久tv | 99热免费在线| 国产乱码精品一区二区三区中文 | 久草免费电影 | 国产日韩一区二区 | 亚洲国产一区二区三区在线观看 | 欧美日韩中文字幕在线播放 | 欧美日韩精品久久久免费观看 | 久久国产精彩视频 | 91久久精品日日躁夜夜躁国产 | 69av片| 黄色av网站在线观看 | 欧美自拍网站 | 国产精品久久777777 | 久久亚洲高清 | 国产精品久久国产精品久久 | 性高湖久久久久久久久aaaaa | 成人免费视频网站在线观看 | 成人中文字幕在线 | 亚洲国产精品一区二区第一页 | 美女逼网站 | m豆传媒在线链接观看 | 羞羞视频在线观看 | 欧美一区二区三区在线 | 日韩中文电影 | 日韩精品一区二区三区中文在线 | 成人一区二区三区在线观看 | 91在线影院 | 国产在线视频一区二区 | 精品久久香蕉国产线看观看亚洲 | 欧美久久国产精品 | 日韩免费av一区二区 | 成人精品啪啪欧美成 | 亚洲国产网址 | 91精品国产乱码久久蜜臀 | 久久久久国产 | wwww.xxxx免费 |