日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NIO基础详解

發布時間:2025/3/20 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NIO基础详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方“好好學java”,選擇“置頂公眾號”

優秀學習資源、干貨第一時間送達!

好好學java

java知識分享/學習資源免費分享

關注

Netty 是基于Java NIO 封裝的網絡通訊框架,只有充分理解了 Java NIO 才能理解好Netty的底層設計。Java NIO 由三個核心組件組件:

  • Buffer

  • Channel

  • Selector

緩沖區 Buffer

Buffer 是一個數據對象,我們可以把它理解為固定數量的數據的容器,它包含一些要寫入或者讀出的數據。

在 Java NIO 中,任何時候訪問 NIO 中的數據,都需要通過緩沖區(Buffer)進行操作。讀取數據時,直接從緩沖區中讀取,寫入數據時,寫入至緩沖區。NIO 最常用的緩沖區則是 ByteBuffer。下圖是 Buffer 繼承關系圖:

每一個 Java 基本類型都對應著一種 Buffer,他們都包含這相同的操作,只不過是所處理的數據類型不同而已。

通道 Channel

Channel 是一個通道,它就像自來水管一樣,網絡數據通過 Channel 這根水管讀取和寫入。傳統的 IO 是基于流進行操作的,Channle 和類似,但又有些不同:

區別流通過Channel
支持異步不支持支持
是否可雙向傳輸數據不能,只能單向可以,既可以從通道讀取數據,也可以向通道寫入數據
是否結合 Buffer 使用必須結合 Buffer 使用
性能較低較高

正如上面說到的,Channel 必須要配合 Buffer 一起使用,我們永遠不可能將數據直接寫入到 Channel 中,同樣也不可能直接從 Channel 中讀取數據。都是通過從 Channel 讀取數據到 Buffer 中或者從 Buffer 寫入數據到 Channel 中,如下:

簡單點說,Channel 是數據的源頭或者數據的目的地,用于向 buffer 提供數據或者讀取 buffer 數據,并且對 I/O 提供異步支持。

下圖是 Channel 的類圖(http://blog.csdn.net/tsyj810883979/article/details/6876594)

Channel 為最頂層接口,所有子 Channel 都實現了該接口,它主要用于 I/O 操作的連接。定義如下:

public interface Channel extends Closeable {/*** 判斷此通道是否處于打開狀態。 */public boolean isOpen();/***關閉此通道。*/public void close() throws IOException; }

最為重要的Channel實現類為:

  • FileChannel:一個用來寫、讀、映射和操作文件的通道

  • DatagramChannel:能通過 UDP 讀寫網絡中的數據

  • SocketChannel: 能通過 TCP 讀寫網絡中的數據

  • ServerSocketChannel:可以監聽新進來的 TCP 連接,像 Web 服務器那樣。對每一個新進來的連接都會創建一個 SocketChannel

多路復用器 Selector

多路復用器 Selector,它是 Java NIO 編程的基礎,它提供了選擇已經就緒的任務的能力。從底層來看,Selector 提供了詢問通道是否已經準備好執行每個 I/O 操作的能力。簡單來講,Selector 會不斷地輪詢注冊在其上的 Channel,如果某個 Channel 上面發生了讀或者寫事件,這個 Channel 就處于就緒狀態,會被 Selector 輪詢出來,然后通過 SelectionKey 可以獲取就緒 Channel 的集合,進行后續的 I/O 操作。

Selector 允許一個線程處理多個 Channel ,也就是說只要一個線程復雜 Selector 的輪詢,就可以處理成千上萬個 Channel ,相比于多線程來處理勢必會減少線程的上下文切換問題。下圖是一個 Selector 連接三個 Channel :

實例

服務端

public class NIOServer {/*接受數據緩沖區*/private ByteBuffer sendbuffer = ByteBuffer.allocate(1024);/*發送數據緩沖區*/private ?ByteBuffer receivebuffer = ByteBuffer.allocate(1024);private Selector selector;public NIOServer(int port) throws IOException {// 打開服務器套接字通道ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 服務器配置為非阻塞serverSocketChannel.configureBlocking(false);// 檢索與此通道關聯的服務器套接字ServerSocket serverSocket = serverSocketChannel.socket();// 進行服務的綁定serverSocket.bind(new InetSocketAddress(port));// 通過open()方法找到Selectorselector = Selector.open();// 注冊到selector,等待連接serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("Server Start----:");}//private void listen() throws IOException {while (true) {selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();iterator.remove();handleKey(selectionKey);}}}private void handleKey(SelectionKey selectionKey) throws IOException {// 接受請求ServerSocketChannel server = null;SocketChannel client = null;String receiveText;String sendText;int count=0;// 測試此鍵的通道是否已準備好接受新的套接字連接。if (selectionKey.isAcceptable()) {// 返回為之創建此鍵的通道。server = (ServerSocketChannel) selectionKey.channel();// 接受到此通道套接字的連接。// 此方法返回的套接字通道(如果有)將處于阻塞模式。client = server.accept();// 配置為非阻塞client.configureBlocking(false);// 注冊到selector,等待連接client.register(selector, SelectionKey.OP_READ);} else if (selectionKey.isReadable()) {// 返回為之創建此鍵的通道。client = (SocketChannel) selectionKey.channel();//將緩沖區清空以備下次讀取receivebuffer.clear();//讀取服務器發送來的數據到緩沖區中count = client.read(receivebuffer);if (count > 0) {receiveText = new String( receivebuffer.array(),0,count);System.out.println("服務器端接受客戶端數據--:"+receiveText);client.register(selector, SelectionKey.OP_WRITE);}} else if (selectionKey.isWritable()) {//將緩沖區清空以備下次寫入sendbuffer.clear();// 返回為之創建此鍵的通道。client = (SocketChannel) selectionKey.channel();sendText="message from server--";//向緩沖區中輸入數據sendbuffer.put(sendText.getBytes());//將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位sendbuffer.flip();//輸出到通道client.write(sendbuffer);System.out.println("服務器端向客戶端發送數據--:"+sendText);client.register(selector, SelectionKey.OP_READ);}}/*** @param args* @throws IOException*/public static void main(String[] args) throws IOException {int port = 8080;NIOServer server = new NIOServer(port);server.listen();} }

客戶端

public class NIOClient {/*接受數據緩沖區*/private static ByteBuffer sendbuffer = ByteBuffer.allocate(1024);/*發送數據緩沖區*/private static ByteBuffer receivebuffer = ByteBuffer.allocate(1024);public static void main(String[] args) throws IOException {// 打開socket通道SocketChannel socketChannel = SocketChannel.open();// 設置為非阻塞方式socketChannel.configureBlocking(false);// 打開選擇器Selector selector = Selector.open();// 注冊連接服務端socket動作socketChannel.register(selector, SelectionKey.OP_CONNECT);// 連接socketChannel.connect(new InetSocketAddress("127.0.0.1", 8080));Set<SelectionKey> selectionKeys;Iterator<SelectionKey> iterator;SelectionKey selectionKey;SocketChannel client;String receiveText;String sendText;int count=0;while (true) {//選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。//此方法執行處于阻塞模式的選擇操作。selector.select();//返回此選擇器的已選擇鍵集。selectionKeys = selector.selectedKeys();//System.out.println(selectionKeys.size());iterator = selectionKeys.iterator();while (iterator.hasNext()) {selectionKey = iterator.next();if (selectionKey.isConnectable()) {System.out.println("client connect");client = (SocketChannel) selectionKey.channel();// 判斷此通道上是否正在進行連接操作。// 完成套接字通道的連接過程。if (client.isConnectionPending()) {client.finishConnect();System.out.println("完成連接!");sendbuffer.clear();sendbuffer.put("Hello,Server".getBytes());sendbuffer.flip();client.write(sendbuffer);}client.register(selector, SelectionKey.OP_READ);} else if (selectionKey.isReadable()) {client = (SocketChannel) selectionKey.channel();//將緩沖區清空以備下次讀取receivebuffer.clear();//讀取服務器發送來的數據到緩沖區中count=client.read(receivebuffer);if(count>0){receiveText = new String( receivebuffer.array(),0,count);System.out.println("客戶端接受服務器端數據--:"+receiveText);client.register(selector, SelectionKey.OP_WRITE);}} else if (selectionKey.isWritable()) {sendbuffer.clear();client = (SocketChannel) selectionKey.channel();sendText = "message from client--";sendbuffer.put(sendText.getBytes());//將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位sendbuffer.flip();client.write(sendbuffer);System.out.println("客戶端向服務器端發送數據--:"+sendText);client.register(selector, SelectionKey.OP_READ);}}selectionKeys.clear();}} }

運行結果

謝謝閱讀,祝好!!!

參考

  • Java NIO 系列教程

  • Netty 權威指南(第2版)

?精彩內容?

你所需要的java基礎篇和提升篇大總結

全網最全電子圖書,你不看看?

你所需要的大數據視頻教程

java全套學習視頻教程和java項目實戰視頻,你不看看?

????????????????????????????????????????????? ? ?? ?? 長按二維碼關注

總結

以上是生活随笔為你收集整理的NIO基础详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲成av人影院 | 伊人66| 最近中文字幕无免费 | 爱爱的网站 | 天天干天天舔 | 婷婷六月丁 | 欧美色视 | 五月深爱婷婷 | 91精品国产综合久 | 久久天天| 九色视频91 | 国产福利一区二区三区视频 | 欧美精品福利 | 激情久久五月天 | 91亚洲国产成人精品性色 | 懂色av成人一区二区三区 | 成人免费不卡视频 | 久久久精品人妻一区二区三区色秀 | 前任攻略在线观看免费完整版 | 亚洲欧洲精品一区二区 | 一级黄色片国产 | 92久久 | 久久嗨 | 亚洲视频在线一区 | 性欧美在线观看 | 无码人妻精品一区二区中文 | 香蕉免费在线视频 | 夜夜成人| 人人艹在线 | 亚洲国产综合视频 | 欧美一级片a | 国产精品伦一区二区三级古装电影 | 上海贵妇尝试黑人洋吊 | 麻豆精品在线播放 | www.超碰97.com| 无码国产精品高潮久久99 | 亚洲自拍偷拍第一页 | 国产伦精品一区二区三区 | 中文字幕高清在线免费播放 | 国产一区=区| 激情图片在线视频 | 91一级视频 | 草久视频在线观看 | 黄色一极毛片 | 奇米影视第四色777 波多野结衣一区二区三区免费视频 | 男人和女人搞鸡 | 欧美精品播放 | 国产www视频 | 尤物视频在线免费观看 | 国产xx在线观看 | 欧美一二| 午夜在线免费视频 | 91视频专区 | 欧美日韩一区二区在线播放 | 亚洲 欧美 国产 另类 | 久久精品亚洲一区二区 | 亚洲欧美日韩国产综合 | 成年人拍拍视频 | 天堂在线观看中文字幕 | 日本xxx在线播放 | 精品久久久无码中文字幕 | 国产精品丝袜黑色高跟 | 久久美女性网 | 国产免费久久 | 人人超碰人人 | 欧美熟妇另类久久久久久不卡 | 久久国内免费视频 | 欧美性视频在线播放 | 国产精品国产三级国产aⅴ下载 | 色播综合网 | 国产性―交一乱―色―情人 | 亚洲一区二区在线观看视频 | 精品欧美乱码久久久久久1区2区 | 国产11页| 国产精品zjzjzj在线观看 | 丁香五香天堂网 | 69精品一区二区 | 韩国三级bd高清中字2021 | 丰满人妻一区二区三区53 | 天堂中文字幕在线观看 | 亚洲五级片| 国产在线看黄 | 国产麻豆一级片 | 在线观看一区二区三区视频 | 2019国产精品| 国产亚洲精品久久久久四川人 | 久久成人精品一区二区 | 丁香美女社区 | 男生坤坤放进女生坤坤里 | 国产aaaaaa | 亚洲欧美自拍一区 | 黄色免费在线观看视频 | 69视频在线播放 | 国产一级一级 | 九月婷婷 | 国产网红在线观看 | 国产sm调教一区二区 | 欧美黄色大全 | 人妖ts福利视频一二三区 |