第一部分:總覽
1.1 解釋
大多數(shù)程序以某種方式與外部世界進(jìn)行交互,無論是通過文件,網(wǎng)絡(luò),串行電報(bào)還是控制臺。 有時(shí)候,就像網(wǎng)絡(luò)一樣,單個(gè)I / O操作可能需要很長時(shí)間才能完成。 這對應(yīng)用程序開發(fā)提出了特別的挑戰(zhàn)。
Asio提供了管理這些長時(shí)間運(yùn)行的操作的工具,而無需程序使用基于線程和顯式鎖定的并發(fā)模型。
Asio庫適用于使用C ++進(jìn)行系統(tǒng)編程的程序員,在這種系統(tǒng)編程中,經(jīng)常需要訪問諸如網(wǎng)絡(luò)等操作系統(tǒng)功能。 特別是,Asio致力于實(shí)現(xiàn)以下目標(biāo):
1 可移植性。 該庫應(yīng)支持一系列常用操作系統(tǒng),并在這些操作系統(tǒng)中提供一致的行為。
2 可擴(kuò)展性。 該庫應(yīng)該能夠促進(jìn)擴(kuò)展到數(shù)千個(gè)并發(fā)連接的網(wǎng)絡(luò)應(yīng)用程序的開發(fā)。 每個(gè)操作系統(tǒng)的庫實(shí)現(xiàn)應(yīng)該使用 最能實(shí)現(xiàn)這種可伸縮性的機(jī)制。
3 效率。 該庫應(yīng)該支持分散/集中式I / O等技術(shù),并允許程序盡量減少數(shù)據(jù)復(fù)制。
4 模型來自于已建立的API,如BSD套接字。 BSD套接字API被廣泛的實(shí)現(xiàn)和理解,并且在許多文獻(xiàn)中都有涉及。 其他編程語言通常使用類似的網(wǎng)絡(luò)API接口。 只要是合理的,Asio應(yīng)該利用現(xiàn)有的做法。
5 使用方便。 庫應(yīng)該通過采用工具包而不是框架方法為新用戶提供較低的進(jìn)入壁壘。也就是說,它應(yīng)該盡量減少前期投資,及時(shí)學(xué)習(xí)一些基本規(guī)則和準(zhǔn)則。 之后,用戶只需要了解正在使用的特定功能。
6 基礎(chǔ)上進(jìn)一步抽象。 應(yīng)該允許開發(fā)提供更高抽象級別的其他庫。 例如,常用協(xié)議(如HTTP)的實(shí)現(xiàn)。
雖然Asio開始主要關(guān)注網(wǎng)絡(luò),但它的異步I / O概念已經(jīng)擴(kuò)展到包括其他操作系統(tǒng)資源,如串行端口,文件描述符等等。
1.2 核心理念和功能
1.2.1 對saio基本解剖
Asio可能用于對I / O對象(如套接字)執(zhí)行同步和異步操作。 在使用Asio之前,先了解一下Asio的各個(gè)部分,程序以及它們?nèi)绾我黄鸸ぷ鞯母拍顖D。
作為一個(gè)介紹性的例子,我們來考慮一下在socket上執(zhí)行連接操作時(shí)會發(fā)生什么。 我們將從檢查同步操作開始。
你的程序至少有一個(gè)io_service對象。 io_service表示您的程序與操作系統(tǒng)的鏈接
I / O服務(wù)。
asio::io_service io_service;
要執(zhí)行I / O操作,您的程序?qū)⑿枰粋€(gè)I / O對象,如TCP套接字:
asio::ip::tcp::socket socket(io_service);
當(dāng)執(zhí)行同步連接操作時(shí),會發(fā)生以下事件序列:
1 您的程序通過調(diào)用I / O對象來啟動連接操作:
socket.connect(server_endpoint);
2 I / O對象將請求轉(zhuǎn)發(fā)給io_service。
3 io_service調(diào)用操作系統(tǒng)來執(zhí)行連接操作
4 操作系統(tǒng)將操作結(jié)果返回給io_service。
5 io_service將操作產(chǎn)生的任何錯(cuò)誤轉(zhuǎn)換為asio :: error_code類型的對象。 error_code可以與特定值進(jìn)行比較,或者作為布爾值進(jìn)行測試(其中錯(cuò)誤結(jié)果表示沒有錯(cuò)誤發(fā)生)。 結(jié)果然后轉(zhuǎn)發(fā)回I / O對象。
6 如果操作失敗,I / O對象將引發(fā)類型為asio :: system_error的異常。
如果啟動操作的代碼被寫為:
asio::error_code ec;
socket.connect(server_endpoint, ec);
那么error_code變量ec將被設(shè)置為操作的結(jié)果,并且不會拋出異常。 當(dāng)使用異步操作時(shí),會發(fā)生不同的事件序列。
1.您的程序通過調(diào)用I / O對象來啟動連接操作:
socket.async_connect(server_endpoint, your_completion_handler);
其中your_completion_handler是帶簽名的函數(shù)或函數(shù)對象:
void your_completion_handler(const asio::error_code& ec);
所需的確切簽名取決于正在執(zhí)行的異步操作。 參考文件指出了每個(gè)操作的適當(dāng)形式。
- I / O對象將請求轉(zhuǎn)發(fā)給io_service。
-
io_service發(fā)信號給操作系統(tǒng),它應(yīng)該啟動一個(gè)異步連接。時(shí)間流逝。 (在同步情況下,這個(gè)等待完全被包含在連接操作的持續(xù)時(shí)間內(nèi)。)
捕獲3.PNG
4.操作系統(tǒng)通過將結(jié)果放在隊(duì)列中表明連接操作已完成,并準(zhǔn)備由io_service接收。
5.您的程序必須調(diào)用io_service :: run()(或類似的io_service成員函數(shù)之一)才能檢索結(jié)果。 調(diào)用io_service :: run()時(shí)會阻塞未完成的異步操作,所以你通常會在您開始第一次異步操作時(shí)立即調(diào)用它。
6.在對io_service :: run()的調(diào)用中,io_service將操作結(jié)果出隊(duì),將其轉(zhuǎn)換為error_code,然后將其傳遞給完成處理程序。 這是Asio如何運(yùn)作的簡單流程圖。 如果您的需求更高級,您將需要深入研究文檔,例如擴(kuò)展Asio以執(zhí)行其他類型的異步操作。
1.2.2 Proactor設(shè)計(jì)模式:沒有線程的并發(fā)
Asio庫為同步和異步操作提供并行支持。 異步支持基于Proactor設(shè)計(jì)模式[POSA2]。 下面概述了這種方法的優(yōu)點(diǎn)和缺點(diǎn),與同步或反應(yīng)器方法相比。
Proactor和Asio
讓我們來看看如何在Asio中實(shí)現(xiàn)Proactor設(shè)計(jì)模式,而不參考平臺特定的細(xì)節(jié)。
Proactor設(shè)計(jì)模式
- 異步操作
-異步操作進(jìn)程 - 完成事件隊(duì)列
- 完成處理程序
- 異步事件解復(fù)用器
- Proactor
- 發(fā)起人
使用反應(yīng)堆
在許多平臺上,Asio使用反應(yīng)器(如select,epoll或kqueue)實(shí)現(xiàn)Proactor設(shè)計(jì)模式。 該實(shí)現(xiàn)方法對應(yīng)于Proactor設(shè)計(jì)模式,如下所示:
- 異步操作處理器
- 完成事件隊(duì)列
- 異步事件解復(fù)用器
使用Windows重疊I / O實(shí)現(xiàn)
在Windows NT,2000和XP上,Asio利用重疊的I / O來提供Proactor設(shè)計(jì)模式的高效實(shí)現(xiàn)。 該實(shí)現(xiàn)方法對應(yīng)于Proactor設(shè)計(jì)模式,如下所示:
- 異步操作處理器
- 完成事件隊(duì)列
- 異步事件解復(fù)用器
優(yōu)點(diǎn)
- 便攜性。
- 從并發(fā)中解耦線程。
- 性能和可擴(kuò)展性。
- 簡化應(yīng)用程序同步。
- 功能組成。
缺點(diǎn)
- 程序復(fù)雜性。
- 內(nèi)存使用。