幾種服務器端IO模型的簡單介紹及實現(轉載)

作者:阿凡盧

出處:http://www.cnblogs.com/luxiaoxun/

服務器端幾種模型:

1、阻塞式模型(blocking IO)

我們第一次接觸到的網絡編程都是從 listen()、accpet()、send()、recv() 等接口開始的。使用這些接口可以很方便的構建C/S的模型。這里大部分的 socket 接口都是阻塞型的。所謂阻塞型接口是指系統調用(一般是 IO 接口)不返回調用結果并讓當前線程一直阻塞,只有當該系統調用獲得結果或者超時出錯時才返回。

如下面一個簡單的Server端實現:

?View Code

示意圖如下:

這里的socket的接口是阻塞的(blocking),在線程被阻塞期間,線程將無法執行任何運算或響應任何的網絡請求,這給多客戶機、多業務邏輯的網絡編程帶來了挑戰。

2、多線程的服務器模型(Multi-Thread)

應對多客戶機的網絡應用,最簡單的解決方式是在服務器端使用多線程(或多進程)。多線程(或多進程)的目的是讓每個連接都擁有獨立的線程(或進程),這樣任何一個連接的阻塞都不會影響其他的連接。

多線程Server端的實現:

?View Code

上述多線程的服務器模型可以解決一些連接量不大的多客戶端連接請求,但是如果要同時響應成千上萬路的連接請求,則無論多線程還是多進程都會嚴重占據系統資源,降低系統對外界響應效率。

在多線程的基礎上,可以考慮使用“線程池”或“連接池”,“線程池”旨在減少創建和銷毀線程的頻率,其維持一定合理數量的線程,并讓空閑的線程重新承擔新的執行任務。“連接池”維持連接的緩存池,盡量重用已有的連接、減少創建和關閉連接的頻率。這兩種技術都可以很好的降低系統開銷,都被廣泛應用很多大型系統。

3、非阻塞式模型(Non-blocking IO)

非阻塞的接口相比于阻塞型接口的顯著差異在于,在被調用之后立即返回。

非阻塞型IO的示意圖如下:

從應用程序的角度來說,blocking read 調用會延續很長時間。在內核執行讀操作和其他工作時,應用程序會被阻塞。

非阻塞的IO可能并不會立即滿足,需要應用程序調用許多次來等待操作完成。這可能效率不高,因為在很多情況下,當內核執行這個命令時,應用程序必須要進行忙碌等待,直到數據可用為止。

另一個問題,在循環調用非阻塞IO的時候,將大幅度占用CPU,所以一般使用select等來檢測”是否可以操作“。

4、多路復用IO

支持I/O復用的系統調用有select、poll、epoll、kqueue等,

這里以Select函數為例,select函數用于探測多個文件句柄的狀態變化,以下為一個使用了使用了Select函數的Server實現:

?View Code

示意圖如下:

這里Select監聽的socket都是Non-blocking的,所以在do_read() do_write()中對返回為EAGAIN/WSAEWOULDBLOCK都做了處理。

從代碼中可以看出使用Select返回后,仍然需要輪訓再檢測每個socket的狀態(讀、寫),這樣的輪訓檢測在大量連接下也是效率不高的。因為當需要探測的句柄值較大時,select?() 接口本身需要消耗大量時間去輪詢各個句柄。

很多操作系統提供了更為高效的接口,如 linux 提供?了 epoll,BSD 提供了 kqueue,Solaris 提供了 /dev/poll …。如果需要實現更高效的服務器程序,類似 epoll 這樣的接口更被推薦。遺憾的是不同的操作系統特供的 epoll 接口有很大差異,所以使用類似于 epoll 的接口實現具有較好跨平臺能力的服務器會比較困難。

5、使用事件驅動庫libevent的服務器模型

Libevent 是一種高性能事件循環/事件驅動庫。

為了實際處理每個請求,libevent 庫提供一種事件機制,它作為底層網絡后端的包裝器。事件系統讓為連接添加處理函數變得非常簡便,同時降低了底層IO復雜性。這是 libevent 系統的核心。

創建 libevent 服務器的基本方法是,注冊當發生某一操作(比如接受來自客戶端的連接)時應該執行的函數,然后調用主事件循環 event_dispatch()。執行過程的控制現在由 libevent 系統處理。注冊事件和將調用的函數之后,事件系統開始自治;在應用程序運行時,可以在事件隊列中添加(注冊)或?刪除(取消注冊)事件。事件注冊非常方便,可以通過它添加新事件以處理新打開的連接,從而構建靈活的網絡處理系統。

使用Libevent實現的一個回顯服務器如下:

?View Code

6、信號驅動IO模型(Signal-driven IO)

使用信號,讓內核在描述符就緒時發送SIGIO信號通知應用程序,稱這種模型為信號驅動式I/O(signal-driven I/O)。

圖示如下:

首先開啟套接字的信號驅動式I/O功能,并通過sigaction系統調用安裝一個信號處理函數。該系統調用將立即返回,我們的進程繼續工作,也就是說進程沒有被阻塞。當數據報準備好讀取時,內核就為該進程產生一個SIGIO信號。隨后就可以在信號處理函數中調用recvfrom讀取數據報,并通知主循環數據已經準備好待處理,也可以立即通知主循環,讓它讀取數據報。

無論如何處理SIGIO信號,這種模型的優勢在于等待數據報到達期間進程不被阻塞。主循環可以繼續執行?,只要等到來自信號處理函數的通知:既可以是數據已準備好被處理,也可以是數據報已準備好被讀取。

7、異步IO模型(asynchronous IO)

異步I/O(asynchronous I/O)由POSIX規范定義。演變成當前POSIX規范的各種早起標準所定義的實時函數中存在的差異已經取得一致。一般地說,這些函數的工作機制是:告知內核啟動某個操作,并讓內核在整個操作(包括將數據從內核復制到我們自己的緩沖區)完成后通知我們。這種模型與前一節介紹的信號驅動模型的主要區別在于:信號驅動式I/O是由內核通知我們何時可以啟動一個I/O操作,而異步I/O模型是由內核通知我們I/O操作何時完成。

示意圖如下:

我們調用aio_read函數(POSIX異步I/O函數以aio_或lio_開頭),給內核傳遞描述符、緩沖區指針、緩沖區大小(與read相同的三個參數)和文件偏移(與lseek類似),并告訴內核當整個操作完成時如何通知我們。該系統調用立即返回,并且在等待I/O完成期間,我們的進程不被阻塞。本例子中我們假設要求內核在操作完成時產生某個信號,該信號直到數據已復制到應用進程緩沖區才產生,這一點不同于信號驅動I/O模型。

?

參考:

《UNIX網絡編程》

使用 libevent 和 libev 提高網絡應用性能:http://www.ibm.com/developerworks/cn/aix/library/au-libev/

使用異步 I/O 大大提高應用程序的性能:https://www.ibm.com/developerworks/cn/linux/l-async/

?

作者:阿凡盧
出處:http://www.cnblogs.com/luxiaoxun/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

轉載于:https://www.cnblogs.com/lizhanwu/articles/4169734.html

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

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

相關文章

html細邊框表格代碼,html中表格細邊框的四種實現及其比較.doc

html中表格細邊框的四種實現及其比較?html中表格細邊框的四種實現及其比較第一種使用css!--- 華麗的分隔線。。 -- .box ?border-top-width: 1px;?border-right-width: 0px;?border-bottom-width: 0px;?border-left-width: 1px;?border-top-style: solid;?border-right-…

margin 等高布局

<div id"main"><div id"left">我是左邊的內容的啦啦啦啦。。。。<br> 我是左邊的內容的啦啦啦啦。。。。<br> 我是左邊的內容的啦啦啦啦。。。。<br> 我是左邊的內容的啦啦啦啦。。。。<br> 我是左邊的內容的啦啦啦啦…

c、c++---linux上的GetTickCount函數

http://blog.csdn.net/guang11cheng/article/details/6865992 http://wenda.so.com/q/1378766306062794

C#判斷一個類中有無指定名稱的方法

C#中可以通過反射分析元數據來解決這個問題&#xff0c;示例代碼如下&#xff1a;12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849using System;using System.Reflection;namespace Hello{class Program{static void Main(string[…

2021年高考成績查詢襄陽狀元,大膽猜測一下,2021年高考,湖北省文理狀元會花落誰家?...

隨著2021年高考的逼近&#xff0c;考生進入緊張有序的復習中&#xff0c;家長也在為孩子籌謀著哪所學校更適合&#xff0c;作為吃瓜群眾的我們&#xff0c;可能更關注今年湖北省的文理科狀元會花落誰家&#xff0c;要知道&#xff0c;一所學校如果可以出現一名高考狀元&#xf…

為什么寫Java程序需要接口

為什么寫Java程序需要接口 我之所以以這個作為標題&#xff0c;并不是為了玩噱頭&#xff0c;講一些似是而非的空話&#xff0c;還是以探索加發現&#xff0c; 追本溯源的講解一下為什么Java需要接口&#xff0c;怎么理解&#xff0c;怎么用它。 首先接口并不是Java才有的&…

《領域特定語言》一1.5使用代碼生成

1.5使用代碼生成 在迄今為止的討論中&#xff0c;要處理DSL&#xff0c;組裝“語義模型”&#xff08;第11章&#xff09;&#xff0c;然后執行語義模型&#xff0c;提供我們希望從控制器得到的行為。在語言圈子里&#xff0c;這種方式稱為解釋&#xff08;interpretation&…

SVG 基礎圖形

SVG 基礎圖形 SVG包含了以下的基礎圖形元素&#xff1a; 矩形&#xff08;包括可選的圓角&#xff09;&#xff0c;使用<rect>元素創建圓形&#xff0c;使用<circle>元素創建橢圓形&#xff0c;使用<ellipse>元素創建直線&#xff0c;使用<line>元素創…

棗莊三中高考2021成績查詢,2021棗莊中考成績查詢系統入口

2021棗莊中考成績查詢系統入口2021-05-20 19:11:35文/王佳慧2021年&#xff0c;棗莊的中考時間快到了&#xff0c;本文分享了棗莊中考成績查詢入口&#xff0c;系統開通后考生可登陸查詢成績。棗莊中考成績查詢入口志愿填報須知1.錄取標準&#xff1a;提前批、第一批、第三批學…

移動端”宴席知多少

轉載(http://adt.aicai.com/index.php/archives/179/) 瞎折騰移動端的項目已經很長一段時間了&#xff0c;并不像其它企業一樣&#xff0c;可以有項目組去完成&#xff0c;基本都是一個人瞎嘗試&#xff0c;時而web&#xff0c;時而web app。恍恍惚惚過了這段歲月&#xff0c;也…

快速的取整方法(~~)

為什么80%的碼農都做不了架構師&#xff1f;>>> 最近看一篇js裝逼小技巧————雙波浪號的妙用(將內容轉化為數字,或者小數取整)&#xff0c;但是本身我的JavaScript水平比較低對其底層操作和其使用范圍不甚了解&#xff1b;通過翻閱資料現進行簡單的整理。 ###裝…

git log友好顯示

查看commit 提交日志 $ git log $git log --prettyoneline $git reflog 顯示所有提交記錄&#xff0c;包括已經回退的提交&#xff0c;如圖&#xff1a;提交了abc 和 bb 然后回退到 abc   $git log 只顯示abc提交 可以使用 $git reset --hard commit號 回退到bb git reflog…

jprofiler_windows-x64_9_1注冊碼

L-Larry_Lau163.com#5481-ucjn4a16rvd98#6038 L-Larry_Lau163.com#36573-fdkscp15axjj6#25257 轉載于:https://www.cnblogs.com/sprinng/p/5104507.html

南理工計算機技術專業學位,南京理工大學計算機技術(專業學位)考研難嗎

很多考生在準備南京理工大學計算機技術(專業學位)考研難嗎&#xff1f;是考研報考的時候都會產生這樣的疑問&#xff1a;這個專業的研究生好嗎&#xff1f;適合我嗎&#xff1f;對我以后的人生和職業會有幫助嗎&#xff1f;考生在準備南京理工大學計算機技術(專業學位)專業考研…

《分布式系統:概念與設計》一2.3.2 體系結構模式

2.3.2 體系結構模式 體系結構模式構建在上述討論過的相對原始的體系結構元素之上&#xff0c;提供組合的、重復出現的結構&#xff0c;這些結構在給定的環境中能運行良好。它們未必是完整的解決方案&#xff0c;但當與其他模式組合時&#xff0c;它們會更好地引導設計者給出一…

javascript sort()實現元素json對象的排序

看以下代碼&#xff1a; var s [ { name: "Robin Van PurseStrings", age: 30 } ,{ name: "Theo Walcott", age: 24 } ,{ name: "Bacary Sagna", age: 28 } ].sort(function(obj1, obj2) {// 實現增序排列&#xff1a;前者的 age 小于后者…

html5手機簽名,html5手寫簽名

var canvas, board;canvas document.getElementById(myCanvas);canvas.height 300;canvas.width 400;board canvas.getContext(2d);board.lineWidth 1; //設置畫筆粗細board.strokeStyle "#f00";board.lineJoin "round"; //設置畫筆軌跡基于圓點拼接…

調查:Java程序員最傷心,C++程序員最年老

說起我們對編程世界現有的刻板印象&#xff0c;你一定聽說過類似于沒有人喜歡用Java編碼或者使用C 都是老人家&#xff0c;等等這樣的話。為了分析這些刻板印象背后的真相&#xff0c;Trestle Technology的數據工程師寫了一個工具。 不知道你有沒有聽說過微軟的Project Oxford&…

mysql一些寫常用命令

參見pcttcnc2007博客騰飛 1.mysql的status信息命令: mysql> show global status; 2.可以列出mysql服務器運行各種狀態值&#xff0c;另外&#xff0c;查詢mysql服務器配置信息語句&#xff1a; mysql> show variables; 3.連接數 經 常會遇見”mysql: error 1040: too man…

計算機不小心刪除怎么找回桌面,如何將桌面上誤刪的文件找回

在如今工作電腦化的趨勢下&#xff0c;用戶都會在桌面上創建各種各樣的文件等&#xff0c;這些文件都是需要在工作中經常要進行各種操作的重要文件&#xff0c;那么頻繁的操作也會出現各種的意外情況等&#xff0c;如果不小心刪除了重要的文件該怎么恢復呢&#xff1f;想要恢復…