網絡I/O模型詳解-一次了解全部(面試經常會問到相關知識)

在這里插入圖片描述

前言

網絡I/O模型的五種類型,其實在我們開發程序、設計程序、實現程序的方方面面都一直存在著,本文從實現原理、使用場景、優缺點、詳細的流程圖等方面進行深入的解釋,幫助大家更好的理解常用的五種網絡io模型,助力大家在工作、面試中做到心中有數、游刃有余理解這些概念知識,也有助于大家程序的設計實現思路的擴展與豐富希望大家會喜歡,也希望對你有所幫助。

網絡I/O模型詳解

概述

網絡I/O模型是操作系統處理網絡數據傳輸的不同策略和機制。根據UNIX網絡編程中的經典分類,主要有五種I/O模型:阻塞I/O、非阻塞I/O、I/O多路復用、信號驅動I/O和異步I/O。每種模型在處理網絡請求時的行為、性能特點和適用場景都有所不同。


1. 阻塞I/O (Blocking I/O)

定義

阻塞I/O是最傳統和直觀的I/O模型。當應用程序調用I/O操作時,線程會被阻塞,直到數據準備好并復制到應用程序緩沖區后才返回。

實現原理

  1. 應用程序調用系統調用(如recv())
  2. 內核檢查數據是否準備好
  3. 如果數據未準備好,進程進入睡眠狀態
  4. 數據準備好后,內核將數據從內核空間復制到用戶空間
  5. 系統調用返回,進程繼續執行

使用場景

  • 簡單的客戶端程序
  • 連接數較少的服務器
  • 對并發要求不高的應用
  • 傳統的CGI程序

優點

  • 編程簡單:邏輯清晰,易于理解和調試
  • 資源占用少:單個連接資源消耗較小
  • 數據完整性好:數據讀取完整,不會出現部分讀取問題
  • 同步處理:程序執行順序明確

缺點

  • 并發能力差:一個線程只能處理一個連接
  • 資源浪費:線程阻塞時CPU資源被浪費
  • 擴展性差:連接數增加時性能下降明顯
應用程序內核網絡recv()系統調用進程阻塞等待數據到達數據到達數據準備完成數據從內核復制到用戶空間返回數據進程繼續執行應用程序內核網絡

2. 非阻塞I/O (Non-blocking I/O)

定義

非阻塞I/O允許應用程序在數據未準備好時立即返回,而不是等待。應用程序需要不斷輪詢來檢查數據是否可用。

實現原理

  1. 應用程序調用系統調用(如recv())
  2. 內核立即檢查數據狀態
  3. 如果數據未準備好,立即返回錯誤碼(如EWOULDBLOCK)
  4. 應用程序繼續執行其他任務或再次輪詢
  5. 當數據準備好時,內核復制數據并返回

使用場景

  • 需要處理多個I/O操作的應用
  • 實時性要求較高的系統
  • 游戲服務器的網絡處理
  • 簡單的異步處理需求

優點

  • 響應性好:不會因為I/O阻塞影響其他操作
  • 資源利用率高:可以在等待I/O時處理其他任務
  • 簡單的并發:單線程就能處理多個連接
  • 實時性強:能夠及時響應其他事件

缺點

  • CPU消耗高:頻繁的輪詢消耗CPU資源
  • 編程復雜:需要處理輪詢邏輯
  • 延遲不確定:數據可用性檢測存在延遲
  • 忙等待:無數據時仍在循環檢查
應用程序內核網絡recv()系統調用(非阻塞)立即返回EWOULDBLOCK處理其他任務數據已到達數據從內核復制到用戶空間返回數據處理接收到的數據alt[數據未準備好][數據準備好]loop[輪詢檢查]應用程序內核網絡

3. I/O多路復用 (I/O Multiplexing)

定義

I/O多路復用通過單個線程監控多個文件描述符的狀態變化,當任何一個描述符準備好時,系統調用返回,告知應用程序哪些描述符可以進行I/O操作。

實現原理

  1. 應用程序調用select/poll/epoll等系統調用
  2. 內核監控多個文件描述符的狀態
  3. 當任何一個描述符準備好時,系統調用返回
  4. 應用程序對準備好的描述符進行I/O操作
  5. 繼續下一輪監控

使用場景

  • 高并發網絡服務器(如Nginx、Redis)
  • 網絡代理服務器
  • 聊天服務器
  • Web服務器的連接管理

優點

  • 高并發支持:單線程可處理數千個連接
  • 資源效率高:避免了為每個連接創建線程
  • 可擴展性好:連接數增加時性能下降緩慢
  • 事件驅動:只在有事件時才處理,效率高

缺點

  • 編程復雜:需要維護狀態機和事件處理
  • 內存拷貝:數據仍需從內核拷貝到用戶空間
  • 跨平臺差異:不同系統的API差異較大
  • 調試困難:異步邏輯的調試較為復雜
應用程序內核描述符1描述符2描述符Nselect/poll/epoll(fd1,fd2,...,fdN)進程阻塞,等待任一描述符就緒監控狀態監控狀態監控狀態par[并行監控]數據準備好返回fd2就緒read(fd2)返回fd2的數據處理完成,繼續下一輪監控應用程序內核描述符1描述符2描述符N

4. 信號驅動I/O (Signal-driven I/O)

定義

信號驅動I/O允許應用程序在數據準備好時通過信號通知,而不是主動輪詢或阻塞等待。應用程序注冊信號處理函數,當數據可用時內核發送信號。

實現原理

  1. 應用程序為SIGIO信號安裝信號處理函數
  2. 通過fcntl設置套接字為信號驅動模式
  3. 應用程序繼續執行其他任務
  4. 當數據準備好時,內核發送SIGIO信號
  5. 信號處理函數被調用,進行實際的I/O操作

使用場景

  • UDP套接字通信
  • 實時數據處理系統
  • 嵌入式系統的網絡模塊
  • 簡單的異步I/O需求

優點

  • 異步通知:無需主動輪詢,由內核主動通知
  • 資源效率:CPU不會因輪詢而浪費
  • 響應及時:數據到達即可得到通知
  • 編程相對簡單:比I/O多路復用更直觀

缺點

  • 信號開銷:信號處理有一定開銷
  • 信號丟失:高頻率信號可能丟失
  • 可移植性差:不是所有系統都支持
  • TCP支持有限:主要適用于UDP
應用程序內核信號處理函數網絡注冊SIGIO信號處理函數fcntl(fd, F_SETFL, O_ASYNC)繼續執行其他任務數據到達數據準備完成發送SIGIO信號recv()讀取數據返回數據處理接收到的數據應用程序內核信號處理函數網絡

5. 異步I/O (Asynchronous I/O)

定義

異步I/O是真正的異步模型,應用程序發起I/O請求后立即返回,內核完成整個I/O操作(包括數據拷貝)后通知應用程序。這是唯一一個在兩個階段都不阻塞的模型。

實現原理

  1. 應用程序調用異步I/O函數(如aio_read)
  2. 內核立即返回,應用程序繼續執行
  3. 內核在后臺等待數據準備
  4. 數據準備好后,內核自動將數據拷貝到用戶緩沖區
  5. 內核通過信號或回調通知應用程序操作完成

使用場景

  • 高性能數據庫系統
  • 文件服務器
  • 大數據處理系統
  • 需要極高性能的網絡應用

優點

  • 真正異步:兩個階段都不阻塞
  • 性能最優:CPU利用率最高
  • 并發能力強:可以同時發起大量I/O操作
  • 擴展性最好:適合高并發場景

缺點

  • 編程最復雜:需要處理復雜的異步邏輯
  • 調試困難:異步操作的調試和錯誤處理復雜
  • 平臺支持有限:不是所有平臺都完全支持
  • 學習成本高:開發人員需要深入理解異步編程
應用程序內核后臺處理網絡aio_read()異步讀取請求立即返回,不阻塞繼續執行其他任務啟動后臺I/O操作等待數據到達數據到達數據從內核拷貝到用戶緩沖區par[后臺異步處理]I/O操作完成通過信號/回調通知完成處理已完成的I/O結果應用程序內核后臺處理網絡

各種I/O模型對比總結

特性阻塞I/O非阻塞I/OI/O多路復用信號驅動I/O異步I/O
阻塞性完全阻塞不阻塞阻塞在select不阻塞完全不阻塞
并發能力一般很好最好
CPU利用率中等最高
編程復雜度最簡單簡單復雜中等最復雜
適用場景簡單應用簡單異步高并發服務器UDP通信高性能系統
擴展性一般最好

現代編程語言中的I/O模型實現

Go語言

  • 基于I/O多路復用的netpoller
  • Goroutine提供同步編程體驗
  • 底層使用epoll/kqueue實現高性能

Node.js

  • 基于異步I/O的事件循環
  • libuv提供跨平臺異步I/O支持
  • 單線程事件驅動模型

Java NIO

  • 提供非阻塞I/OI/O多路復用
  • Selector機制實現多路復用
  • 支持異步I/O (AIO)

Python asyncio

  • 基于I/O多路復用的異步框架
  • async/await語法糖
  • 事件循環調度協程

總結

選擇合適的I/O模型需要根據具體的應用場景、性能要求和開發復雜度來決定:

  1. 簡單應用:使用阻塞I/O即可
  2. 中等并發:考慮非阻塞I/O或I/O多路復用
  3. 高并發服務器:首選I/O多路復用
  4. 極高性能要求:考慮異步I/O
  5. UDP應用:可以考慮信號驅動I/O

現代高性能網絡應用大多采用I/O多路復用模型,因為它在性能和復雜度之間取得了良好的平衡。

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

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

相關文章

面試150 合并K個升序鏈表

思路 對鏈表元素進行獲取,然后進行sort()排序,最后通過空節點建立鏈表法重新建立一個有序的鏈表,返回頭節點即可。 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val …

BitDistiller:通過自蒸餾釋放 Sub-4-Bit 大語言模型的潛力

溫馨提示: 本篇文章已同步至"AI專題精講" BitDistiller:通過自蒸餾釋放 Sub-4-Bit 大語言模型的潛力 摘要 大語言模型(LLMs)的規模不斷擴大,在自然語言處理方面取得了令人矚目的進展,但這也帶來…

JavaScript 的 `querySelector` 方法詳解

querySelector 是 JavaScript 中用于選擇 DOM 元素的最強大方法之一,它允許你使用 CSS 選擇器語法來查找元素。 基本語法 // 返回文檔中第一個匹配指定 CSS 選擇器的元素 element document.querySelector(selectors);// 從指定元素后代中查找 element parentEle…

第九講:C++中的list與forward_list

目錄 1、list的介紹及使用 1.1、構造及賦值重載 1.2、迭代器 1.3、空間 1.4、訪問 1.5、修改 1.6、操作 2、迭代器失效 3、list的模擬實現 4、forward_list介紹與使用 4.1、構造及賦值重載 4.2、迭代器 4.3、容量 4.4、訪問 4.5、修改 4.6、操作 5、迭代器的分…

華為云數據庫 GaussDB的 nvarchar2隱式類型轉換的坑

bigint 與 nvarchar2比較時發生隱式類型轉換的坑 1. 案例分析 假設: table1有下面兩個字段:id:bigint, source_id nvarchar2(50)數據庫中id 的值一定大于 int4 的最大值,例如存在一條單據: id1947854462980792321&…

spring boot 集成netty,及其一些基本概念

一、基本概念 1、channel:通道,入站或者出站數據的載體 2、ChannelHandler:通道處理器,業務邏輯寫在這里面,netty 5版本將入戰和出站合并成了ChannelHandler 3、ChannelPipeline:通道里的管道,是一個或者多…

7月23日華為機考真題第一題100分

?? 點擊直達筆試專欄 ??《大廠筆試突圍》 ?? 春秋招筆試突圍在線OJ ?? bishipass.com 01. 創業投資收益優化 問題描述 K小姐剛剛大學畢業,手頭有 m m m 元資金想要進行創業投資。她發現了 k k

HTML5 跨文檔通信機制:postMessage API 詳解與應用

postMessage 是 HTML5 規范中定義的跨文檔通信(Cross-Document Messaging)API,其設計目的是解決不同源(協議、域名、端口任一存在差異)的窗口(如 iframe 嵌入的文檔、window.open 創建的新窗口)…

Kafka——Kafka中的位移提交

引言:為什么位移提交至關重要?在Kafka的分布式消息系統中,消費者組(Consumer Group)通過分區分配機制實現負載均衡和容錯,但如何準確記錄每個消費者的消費進度,是保證消息不丟失、不重復的關鍵。…

java設計模式 -【裝飾器模式】

裝飾器模式的定義 裝飾器模式(Decorator Pattern)是一種結構型設計模式,允許向一個現有對象動態添加新功能,同時不改變其結構。它通過創建包裝對象(裝飾器)來包裹原始對象,并在保持原始對象方法…

手寫字體生成器:一鍵模擬真實筆跡

軟件介紹 在自媒體創作領域,手寫體文案因其獨特的藝術感而備受青睞。然而,真實的手寫往往效率低下且效果難以保證。今天為大家推薦一款專業的手寫模擬軟件,能夠一鍵生成逼真的手寫字體效果,完美解決創作效率與質量的雙重需求。…

【Android】用 ViewPager2 + Fragment + TabLayout 實現標簽頁切換

文章目錄【Android】用 ViewPager2 Fragment TabLayout 實現標簽頁切換一、引入:什么是 ViewPager2 ?二、ViewPager2 的基礎使用1. 在布局文件 (activity_main.xml)中添加 ViewPager22. 制作一個 Fragment2.1 創建一個布局文件2.2 創建一個 Fragment 類…

嵌入式學習-土堆目標檢測(4)-day28

Pytorch中加載自定義數據集 - VOC其中需要pip install xmltodict#voc_dataset.pyimport os import torch import xmltodict from PIL import Image from torch.utils.data import Dataset import torchvision.transforms as transformsclass VOCDataset(Dataset): def __init_…

Spring MVC上下文容器在Web容器中是如何啟動的(源碼深入剖析)?

文章目錄一、雙容器架構:MVC容器與根容器的關系二、啟動全流程解析1. 啟動流程全景圖2. 初始化根容器(Root WebApplicationContext)2.1 Tomcat 中啟動入口源碼解析2.2 Spring 根上下文啟動源碼解析3. 初始化 MVC 容器(DispatcherS…

【iOS】編譯和鏈接、動靜態庫及dyld的簡單學習

文章目錄編譯和鏈接1??核心結論:一句話區分2??編譯過程:從源代碼到目標文件(.o)2.1 預處理(Preprocessing):“替換變量復制粘貼”2.2 編譯(Compilation):…

金山辦公WPS項目產品總監陳智新受邀為第十四屆中國PMO大會演講嘉賓

全國PMO專業人士年度盛會珠海金山辦公軟件有限公司WPS項目產品總監 陳智新先生 受邀為“PMO評論”主辦的2025第十四屆中國PMO大會演講嘉賓,演講議題為:中小團隊PMO的成長之路,敬請關注!議題簡要:在競爭激烈、需求多變的…

web安全 | docker復雜環境下的內網打點

本文作者:Track-syst1m一.前言本文涉及的相關漏洞均已修復、本文中技術和方法僅用于教育目的;文中討論的所有案例和技術均旨在幫助讀者更好地理解相關安全問題,并采取適當的防護措施來保護自身系統免受攻擊。二.大概流程1. 外網打點? 漏洞利…

iTwin 幾何屬性獲取

面積體積半徑獲取幾何屬性,如面積,體積,半徑,可以使用getMassProperties這個接口async onGetMassProperty(){const vp IModelApp.viewManager.selectedView;const iModel vp?.iModel;if (!iModel) return;console.log("iM…

OpenLayers 快速入門(九)Extent 介紹

看過的知識不等于學會。唯有用心總結、系統記錄,并通過溫故知新反復實踐,才能真正掌握一二 作為一名摸爬滾打三年的前端開發,開源社區給了我飯碗,我也將所學的知識體系回饋給大家,助你少走彎路! OpenLayers…

LeetCode 121. 買賣股票的最佳時機 LeetCode 122. 買賣股票的最佳時機II LeetCode 123.買賣股票的最佳時機III

LeetCode 121. 買賣股票的最佳時機嘗試一:暴力解決方法常用兩個指針去遍歷prices數組,dp[i]用于記錄在第i天所獲得的最大利潤。時間復雜度是O(N^2),超出時間限制。Codeclass Solution(object):def maxProfit(self, prices):"""…