NIO簡單介紹和運用

  • NIO簡單介
    NIO 非阻塞IO模型,基于緩沖區(Buffer)讀寫數據,讀寫后的數據通過通道(Channel)進行傳輸,采用選擇器(Selector)管理多個通道從而實現高并發。
    核心組件:1. Buffer 為一個內存數組作為數據容器,代替傳統的InputStream和OutputStream;2. Channel 雙向數據傳輸;3. Selector 監聽多通道區別于傳統的單線程管理多連接
  • 傳統的IO模型
    阻塞、非阻塞、多路復用、信號驅動、異步IO
  • 簡單的NIO服務器接收客戶端TCP請求
 public void start(int port) throws IOException {//創建一個選擇器管理通道Selector selector = Selector.open();//創建通道并注冊到選擇器(可創建多個通道)createChannel(selector, port);while (true) {//阻塞,等到有事件發生時繼續執行selector.select();//處理事件Iterator<SelectionKey> keys = selector.selectedKeys().iterator();while (keys.hasNext()) {SelectionKey key = keys.next();keys.remove();//新連接到達if (key.isAcceptable()) {ServerSocketChannel socketChannel = (ServerSocketChannel) key.channel();SocketChannel channel = socketChannel.accept();channel.configureBlocking(false);//注冊新的讀取事件channel.register(selector, SelectionKey.OP_READ);continue;}//可讀取數據if (key.isReadable()) {SocketChannel channel = (SocketChannel) key.channel();//定義讀取數據的緩沖區ByteBuffer buffer = ByteBuffer.allocate(1024);//讀取數據到緩沖int bytes = channel.read(buffer);//客戶端關閉連接if (bytes == -1) {channel.close();continue;}//切換為讀取模式buffer.flip();String message = new String(buffer.array(), 0, bytes);System.out.println("接收到消息");//回顯消息給客戶端channel.write(ByteBuffer.wrap(message.getBytes()));}}}}
private void createChannel(Selector selector, int port) throws IOException {//創建通道并綁定端口ServerSocketChannel socketChannel = ServerSocketChannel.open();socketChannel.bind(new InetSocketAddress(port));//設置為非阻塞socketChannel.configureBlocking(false);//將通道注冊到選擇器socketChannel.register(selector, SelectionKey.OP_ACCEPT);}
  • Netty基于NIO的異步事件驅動的網絡應用框架
    特性:異步和事件驅動、高性能(高效的線程模型和緩沖區機制)、易使用和靈活可擴展
    涉及到 channel 、callback(事件發生時的回調)、Future和Promise(異步計算)、EventLoop(事件循環)、Pipeline和ChannelHandler管道和處理器、bootstrap引導類
 public static void start(int port) {// 創建兩個EventLoopGroup事件循環組,一個用于接收客戶端連接,一個用于處理客戶端數據EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {start(bossGroup, workerGroup, port);} catch (Exception e) {log.warn("Netty服務【{}】發生異常", port, e);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
private static void start(EventLoopGroup bossGroup, EventLoopGroup workerGroup, int port) throws InterruptedException {//創建服務器啟動對象ServerBootstrap serverBootstrap = new ServerBootstrap();//parentGroup:這個事件組用于接收客戶端的連接請求。它會創建一個ServerChannel,用于監聽并接收客戶端的連接。一旦有連接請求到達,parentGroup就會將連接分配給childGroup中的一個EventLoop來處理。//childGroup:這個事件組用于處理接收到的連接的數據。它會創建一個或多個Channel,用于與客戶端進行通信。每個Channel都有一個關聯的EventLoop,用于處理該Channel的I/O操作。childGroup會負責管理這些Channel和EventLoop,包括事件循環、線程分配、I/O操作等。//通過使用兩個不同的事件組,可以實現多線程處理客戶端連接和數據的模型。parentGroup負責接收連接請求并將其分配給childGroup處理,childGroup負責處理具體的連接和數據操作,從而提高服務器的并發性能。serverBootstrap.group(bossGroup, workerGroup)//.option(ChannelOption)可設置其它各種參數//服務器通道實現采用NioServerSocketChannel.channel(NioServerSocketChannel.class)//針對服務端的所有連接(不論已連接或是創建連接).handler(new LoggingHandler())//針對已接收到的連接的處理器配置.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) {//添加自定義解碼器,如繼承ByteToMessageCodec用于處理各種業務邏輯,解碼器按添加的先后順尋執行//ByteToMessageCodec主要用于解碼字節數據,將其轉換為消息對象,常用于解決粘包和拆包問題//ChannelInboundHandlerAdapter主要用于處理各種事件,如接收到數據、連接建立、異常處理等,同時為響應請求數據可以用用channel的writeAndFlush將數據寫入并刷新網路socketChannel.pipeline().addLast(new IotDataDecoder(), new IotBusinessDecoder());}});//以下兩行代碼用于確保服務器在綁定端口后一直保持運行狀態,直到接收到關閉信號//綁定服務器端口并啟動服務 sync()使當前線程阻塞直到綁定服務器,綁定多個端口直接重復以下兩行代碼ChannelFuture channelFuture = serverBootstrap.bind(port).sync();//等待服務器關閉channelFuture.channel().closeFuture().sync();}
  • 通過NIO將數據流寫入到本地文件
 private void write(InputStream stream, String targetPath) throws IOException {//創建通道FileChannel outChannel = FileChannel.open(Paths.get(targetPath), StandardOpenOption.CREATE, StandardOpenOption.WRITE);ReadableByteChannel inChannel = Channels.newChannel(stream);//創建緩沖區ByteBuffer buffer = ByteBuffer.allocate(2048);//寫入和讀取while (inChannel.read(buffer) != -1) {//調整緩沖區的位置以便讀取,將位置調整到0buffer.flip();outChannel.write(buffer);//將緩沖區未讀取的位置移動到起始位置buffer.compact();}buffer.flip();//判斷是否有剩余內容while (buffer.hasRemaining()) {outChannel.write(buffer);}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915636.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915636.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode 658.找到K個最接近的元素

給定一個 排序好 的數組 arr &#xff0c;兩個整數 k 和 x &#xff0c;從數組中找到最靠近 x&#xff08;兩數之差最小&#xff09;的 k 個數。返回的結果必須要是按升序排好的。 整數 a 比整數 b 更接近 x 需要滿足&#xff1a; |a - x| < |b - x| 或者 |a - x| |b - x| …

制作一款打飛機游戲83:炸彈機制

游戲中的炸彈系統&#xff0c;包括以下核心功能&#xff1a;炸彈爆炸效果與動畫實現炸彈傷害范圍判定機制子彈轉化為能量道具的系統炸彈使用時的無敵幀處理各種邊界情況的修復與優化技術實現細節1. 炸彈基礎系統?炸彈動畫狀態機?&#xff1a; 我們采用三階段狀態機控制炸彈效…

Linux CentOS 虛擬機升級內核至4.x以上版本

1、安裝組件 yum install -y wget && yum install -y net-tools yum groupinstall “Development Tools” yum install ncurses-devel bc openssl-devel elfutils-libelf-devel yum install -y ncurses-devel yum install -y elfutils-libelf-devel yum install -y ope…

QT跨平臺應用程序開發框架(11)—— Qt系統相關

目錄 一&#xff0c;事件 1.1 關于事件 1.2 處理事件 1.3 處理鼠標事件 1.3.1 點擊事件 1.3.2 釋放事件 1.3.3 雙擊事件 1.3.4 滾輪事件 1.3.5 注意事項 1.4 處理鍵盤事件 1.5 定時器事件 1.6 窗口移動和大小改變事件 二&#xff0c;文件操作 2.1 文件操作概述 2.2 QFile 介紹…

sqli-labs通關筆記-第11關 POST字符型注入(單引號閉合 手工注入+腳本注入兩種方法)

目錄 一、字符型注入 二、limit函數 三、GET方法與POST方法 四、源碼分析 1、代碼審計 2、SQL注入安全分析 五、滲透實戰 1、進入靶場 2、注入點分析 &#xff08;1&#xff09;SQL語句 &#xff08;2&#xff09;萬能密碼登錄 3、手工注入 &#xff08;1&#xf…

網絡安全基礎作業三

回顧web前端的代碼<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>用戶登錄</title><st…

基于單片機的溫濕度報警系統設計與實現

摘 要 本項研究對溫濕度警報系統的需求進行了詳盡分析&#xff0c;并成功研制出一套以單片機為技術核心的溫濕度警報系統。該系統由硬件搭建和軟件編程兩大模塊構成。在硬件搭建方面&#xff0c;系統整合了STM32主控芯片、DS18B20溫度傳感器、濕敏電阻、按鍵組件、OLED顯示屏、…

(八)復習(拆分微服務)

文章目錄項目地址一、Ticketing模塊拆分1.1 創建web api1. 添加引用2. 添加需要的包和配置3. program.cs4. docker-compose修改項目地址 教程作者&#xff1a;教程地址&#xff1a; 代碼倉庫地址&#xff1a; 所用到的框架和插件&#xff1a; dbt airflow一、Ticketing模塊拆…

DearMom以“新生兒安全系統”重塑嬰兒車價值,攬獲CBME雙項大獎

7月16日&#xff0c;在剛剛開幕的2025 CBME中國孕嬰童展上&#xff0c;備受矚目的CBME中國孕嬰童產業獎正式揭曉。深耕嬰兒車品類的專業品牌DearMom&#xff0c;憑借其卓越的創新實力與對新生兒安全出行的深刻洞察&#xff0c;一舉摘得重量級獎項——“杰出品牌創新獎”。同時&…

瀚高數據庫開啟Oracle兼容模塊

文章目錄環境癥狀問題原因解決方案環境 系統平臺&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;4.5 癥狀 不能使用Oracle兼容&#xff1b; 問題原因 在瀚高數據庫V45中oracle兼容模塊需要單獨開啟默認是關閉狀態。 解決方案 使用sysdba執行修改…

final修飾符不可變的底層

final修飾符的底層原理在 Java 中&#xff0c;final 修飾符的底層實現涉及 編譯器優化 和 JVM 字節碼層面的約束其核心目標是保證被修飾元素的【不可變性】或 【不可重寫 / 繼承性】一、final 修飾類&#xff1a;禁止繼承的底層約束當一個類被 final 修飾時&#xff0c;例如 St…

如何排查服務器 CPU 飆高

服務器 CPU 飆高&#xff08;CPU 使用率持續超過 80% 甚至接近 100%&#xff09;是典型的性能瓶頸問題&#xff0c;可能由應用邏輯缺陷、資源競爭、外部壓力或硬件/系統異常引起。以下是系統化的排查步驟&#xff0c;覆蓋從現象確認到根因定位的全流程。?一、確認 CPU 飆高的現…

【DataWhale】快樂學習大模型 | 202507,Task05筆記

前言 今天是Transformer的編碼實戰階段&#xff0c;照著示例代碼執行一遍吧 embedding self.tok_embeddings nn.Embedding(args.vocab_size, args.dim)把token向量轉為embedding矩陣&#xff08;一個token一個embedding向量&#xff09; 位置編碼 為了解決“我喜歡你”和…

用ffmpeg 進行視頻的拼接

author: hjjdebug date: 2025年 07月 22日 星期二 17:06:02 CST descrip: 用ffmpeg 進行視頻的拼接 文章目錄1. 指定協議為concat 方式.1.1 協議為concat 模式,會調用 concat_open 函數1.2 當讀數據時,會調用concat_read2. 指定file_format 為 concat 方式2.1 調用concat_read_…

HTTP與HTTPS技術細節及TLS密鑰交換與證書校驗全流程

HTTP與HTTPS技術細節及TLS密鑰交換與證書校驗全流程 引言 文檔目的與范圍 核心技術棧概述 本文檔的核心技術棧圍繞傳輸層安全協議&#xff08;TLS&#xff09;展開。TLS協議作為安全套接字層&#xff08;SSL&#xff09;的后繼標準&#xff0c;是現代網絡安全通信的基礎&am…

廣播分發中心-廣播注冊流程

廣播是怎么注冊的呢&#xff1f;階段組件/數據結構作用描述存儲位置/關聯關系App進程階段BroadcastReceiver開發者自定義的廣播接收器&#xff0c;實現onReceive方法處理事件。App進程&#xff08;Activity/Service等組件內&#xff09;ReceiverDispatcher將BroadcastReceiver封…

OpenCV計算機視覺實戰(16)——圖像分割技術

OpenCV計算機視覺實戰&#xff08;16&#xff09;——圖像分割技術0. 前言1. 分水嶺算法1.1 應用場景1.2 實現過程2. GrabCut 交互式分割2.1 應用場景2.2 實現過程3. FloodFill3.1 應用場景3.2 實現過程小結系列鏈接0. 前言 圖像分割是計算機視覺中將像素劃分為具有特定語義或…

Coturn打洞服務器

* 概念理解&#xff1a;1. SDP協議&#xff1a;會話描述協議&#xff0c;視頻通話的雙方通過交換SDP信息進行媒體協商&#xff0c;從而選擇使用某一相同的媒體協議進行通信&#xff1b;TLS協議&#xff1a;基于TCP的安全層傳輸協議DTLS協議&#xff1a;基于UDP的安全層傳輸協議…

python flusk 監控

# 創建虛擬環境目錄 python3 -m venv /sda1/xunjian/venv # 激活虛擬環境 source /sda1/xunjian/venv/bin/activate # 激活后終端會顯示 (venv)創建虛擬環境&#xff08;在當前目錄&#xff09;&#xff1a;bashpython3 -m venv venv激活虛擬環境&#xff1a;bashsource venv/b…

VUE2 項目學習筆記 ? 語法 v-if/v-show

?語法頁面渲染的時候&#xff0c;需要服務器傳過來的對象中的一個屬性&#xff0c;然后根據這個屬性用v-for渲染標簽&#xff0c;這里寫的v-for".... in dataList.goodsList"但是當解析到這行語法的時候&#xff0c;dataList還沒返回&#xff0c;因此控制臺會報錯找…