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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Netty - I/O模型之NIO

發布時間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty - I/O模型之NIO 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • Non Blocking I/O 同步非阻塞模型
  • Code
    • Server
    • Client
    • 日志及需要優化的地方
    • 優化 (多路復用器)
  • 小結


Non Blocking I/O 同步非阻塞模型

同步非阻塞

一個線程可以處理多個請求(連接),客戶端發送的連接請求都會注冊到多路復用器selector上,多路復用器輪詢到連接有IO請求就進行處理。

JDK1.4開始引入


Code

Server

package com.artisan.iomodel.nio;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.Iterator; import java.util.List;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/1/17 0:06* @mark: show me the code , change the world*/public class NioServer {// 保存客戶端連接static List<SocketChannel> channelList = new ArrayList<>();public static void main(String[] args) throws IOException {// 創建NIO ServerSocketChannel,與BIO的serverSocket類似ServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(7777));// 設置ServerSocketChannel為非阻塞serverSocket.configureBlocking(false);System.out.println("服務啟動成功");while (true) {// 非阻塞模式accept方法不會阻塞,否則會阻塞// NIO的非阻塞是由操作系統內部實現的,底層調用了linux內核的accept函數SocketChannel socketChannel = serverSocket.accept();if (socketChannel != null) { // 如果有客戶端進行連接System.out.println("連接成功");// 設置SocketChannel為非阻塞socketChannel.configureBlocking(false);// 保存客戶端連接在List中channelList.add(socketChannel);}// 遍歷連接進行數據讀取Iterator<SocketChannel> iterator = channelList.iterator();while (iterator.hasNext()) {SocketChannel sc = iterator.next();ByteBuffer byteBuffer = ByteBuffer.allocate(128);// 非阻塞模式read方法不會阻塞,否則會阻塞int len = sc.read(byteBuffer);// 如果有數據,把數據打印出來if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客戶端斷開,把socket從集合中去掉iterator.remove();System.out.println("客戶端斷開連接");}}}} }

Client

我們用cmd工具來連一下 , telnet 127.0.0.1 7777

回車,輸入 ctrl + ]

發送消息


日志及需要優化的地方

舉個例子,如果連接數太多的話,會有大量的無效遍歷,假如有1萬個連接,其中只有1000個連接有寫數據,但是由于其他9000個連接并沒有斷開,我們還是要每次輪詢遍歷一萬次,其中有十分之九的遍歷都是無效的…是不是有點不妥當呢?


優化 (多路復用器)

為了優化這個問題 , NIO引入多路復用器

package com.artisan.iomodel.nio;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; /*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/1/17 0:50* @mark: show me the code , change the world*/ public class NioSelectorServer {public static void main(String[] args) throws IOException, InterruptedException {// 創建NIO ServerSocketChannelServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(7777));// 設置ServerSocketChannel為非阻塞serverSocket.configureBlocking(false);// 打開Selector處理Channel,即創建epollSelector selector = Selector.open();// 把ServerSocketChannel注冊到selector上,并且selector對客戶端accept連接操作感興趣serverSocket.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服務啟動成功");while (true) {// 阻塞等待需要處理的事件發生selector.select();// 獲取selector中注冊的全部事件的 SelectionKey 實例Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();// 遍歷SelectionKey對事件進行處理while (iterator.hasNext()) {SelectionKey key = iterator.next();// 如果是OP_ACCEPT事件,則進行連接獲取和事件注冊if (key.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel socketChannel = server.accept();socketChannel.configureBlocking(false);// 這里只注冊了讀事件,如果需要給客戶端發送數據可以注冊寫事件socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("客戶端連接成功");} else if (key.isReadable()) { // 如果是OP_READ事件,則進行讀取和打印SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(128);int len = socketChannel.read(byteBuffer);// 如果有數據,把數據打印出來if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客戶端斷開連接,關閉SocketSystem.out.println("客戶端斷開連接");socketChannel.close();}}//從事件集合里刪除本次處理的key,防止下次select重復處理iterator.remove();}}} }


小結

NIO方式適用于連接數目多且連接比較短(輕操作) 的架構, 比如聊天服務器, 彈幕系統, 服務器間通訊,但編程比較復雜

總結

以上是生活随笔為你收集整理的Netty - I/O模型之NIO的全部內容,希望文章能夠幫你解決所遇到的問題。

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