溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Windows完成端口 IOCP模型(一)

發(fā)布時(shí)間:2020-07-19 06:35:34 來源:網(wǎng)絡(luò) 閱讀:9199 作者:超級(jí)極客 欄目:編程語言

1 Windows完成端口基本介紹


2他是只能在Windows下的基于SOCKET事件管理的模型

3與select不同,select需要多次重置管理句柄,IOCP只要一次

4有事件后select需要操作獲取數(shù)據(jù),而IOCP通知你的時(shí)候說明數(shù)據(jù)操作好了

5select管理句柄的數(shù)目有限,IOCP沒有限制

6IOCP支持多線程同時(shí)等待。


我的設(shè)計(jì)思路一個(gè)線程用來偵聽accept事件, 一個(gè)線程來偵聽SOCKET的IO事件,

大部分框架都是這樣, 其實(shí)可以只使用一個(gè)線程做異步SOCKET就完全足夠了,現(xiàn)在

使用多線程來 就是看看這個(gè)IOCP的多線程用法,


在這之前先要了解下 異步通信 和 重疊I/O模型

異步通信機(jī)制: https://blog.51cto.com/blogger/draft/412685

重疊I/O模型: https://blog.51cto.com/12158490/2058180


我建議使用單線程 原因: 應(yīng)為多個(gè)線程,拿到數(shù)據(jù)后,還是要發(fā)送到另外一個(gè)線程里面去,

然后做成事件隊(duì)列, 也就是你線程拿到數(shù)據(jù)后, 還是要按隊(duì)列線程,進(jìn)行邏輯處理,多線程沒意義。



2完成端口內(nèi)部運(yùn)行流程

完成端口的做法:事先開好幾個(gè)線程,你有幾個(gè)CPU我就開幾個(gè),首先是避免了線程的上下文切換,因?yàn)榫€程想要

執(zhí)行的時(shí)候,總有CPU資源可用,然后讓幾個(gè)線程等著,等到有用戶請(qǐng)求到來的時(shí)候,就把這些請(qǐng)求都加入到一個(gè)

公共消息隊(duì)列中, 然后這幾個(gè)開好的線程就排隊(duì)逐一去從消息隊(duì)列中取出消息并加以處理, 這種方式實(shí)現(xiàn)了

異步通信和負(fù)載均衡的問題,因?yàn)樗?span >提供了一種機(jī)制來使用個(gè)線程"公平的"處理來自多個(gè)客戶端的輸入/輸出

,并且線程如果沒事干的時(shí)候,也會(huì)被系統(tǒng)掛起,不會(huì)占用CPU。



3WSAAsyncSelect或者WSAEventSelect和完成端口

WSAAsyncSelect或者WSAEventSelect兩種異步模型, 這兩種模式一定沒有使用overlapped(重疊)機(jī)制,

就不能算是真正的異步,可能是其內(nèi)部維護(hù)了一個(gè)消息隊(duì)列,這兩個(gè)模式雖然實(shí)現(xiàn)了異步接收,卻不能異步的發(fā)送,

完成端口他是先把用戶數(shù)據(jù)接收回來后在通知用戶直接來取,而這兩種模式只會(huì)接到數(shù)據(jù)到達(dá)的通知,只能是由

應(yīng)用程序自己去recv數(shù)據(jù),性能上就發(fā)送了差異

要實(shí)現(xiàn)異步通信, 就要一個(gè)很強(qiáng)的I/O數(shù)據(jù)結(jié)構(gòu),叫重接結(jié)構(gòu)"Overtlapped",

Window所有異步通信都是基于他,完成端口也不例外

就是執(zhí)行I/O請(qǐng)求的時(shí)間與線程執(zhí)行其他任務(wù)的事件是重疊(overlapped)的,


重疊結(jié)構(gòu)是異步通信機(jī)制實(shí)現(xiàn)的一個(gè)核心數(shù)據(jù)結(jié)構(gòu),因?yàn)閹缀跛械木W(wǎng)絡(luò)操作例如發(fā)送/接收,都要用

WSASend()和WSARecv()代替,參數(shù)里面都會(huì)要附帶一個(gè)重疊結(jié)構(gòu),因?yàn)橹丿B機(jī)構(gòu)可以理解為是一個(gè)

網(wǎng)絡(luò)操作的ID號(hào),也就是說我們要利用重疊I/O提供的異步機(jī)制的話,每一個(gè)網(wǎng)絡(luò)操作都要有一個(gè)唯一的ID號(hào),

因?yàn)檫M(jìn)來系統(tǒng)內(nèi)核,一看到有重疊的I/O的調(diào)用進(jìn)來了,就會(huì)使用其異步機(jī)制,并且操作系統(tǒng)就只能靠

這個(gè)重疊結(jié)構(gòu)帶有的ID號(hào)來區(qū)分是哪一個(gè)網(wǎng)絡(luò)操作了,然后內(nèi)核里處理完畢, 根據(jù)這個(gè)ID號(hào),把對(duì)應(yīng)的數(shù)據(jù)傳上去.




4完成端口基本的使用流程 

完成端口也分步驟的

1調(diào)用CreateIoCompletionPort()函數(shù)創(chuàng)建一個(gè)完成端口,而且在一般情況下,我們需要并且只需要

建立一個(gè)完成端口,把他的句柄保存好, 之后只要使用這一個(gè)句柄就行了。

2根據(jù)和客戶的I/O操作最好是自己建一個(gè)工作線程

3接入Socket連接, 有兩種方式,1是和別的模型一樣,有一個(gè)獨(dú)立的線程,專門來accept客戶端的連接,

二是用性能更好的異步AcceptEx()請(qǐng)求

4每當(dāng)有客戶端進(jìn)來的時(shí)候,還是調(diào)用CreateIoCompletionPort()函數(shù),這里不是建立完成端口,

而是把新連入的Socket句柄, 和你創(chuàng)建的完成端口綁定在一起。

5客戶端連入后,我們要向這個(gè)客戶端Socket提交一個(gè)請(qǐng)求,如接收文件要調(diào)用WSARecv()然后系統(tǒng)

就會(huì)去執(zhí)行接收數(shù)據(jù)的操作, 就不用我們管了。

6 然后就要調(diào)用GetQueuedCompletionStatus()(是一個(gè)阻塞函數(shù))里面是掃描端口的隊(duì)列里是否有

網(wǎng)絡(luò)通信的請(qǐng)求存在(例如讀取數(shù)據(jù),發(fā)送數(shù)據(jù)等),一旦有,就會(huì)將這個(gè)請(qǐng)求從完成端口的隊(duì)列取回來,

繼續(xù)執(zhí)行本線程的后續(xù)代碼,處理完畢后, 必須要再次 投遞網(wǎng)絡(luò)通信請(qǐng)求(WSARecv),如此循環(huán)。




5AcceptEx和Accept的區(qū)別

AcceptEx和Accept最大的區(qū)別,就是取消了阻塞方式的accept調(diào)用,也就是說AccentEx也是通過

完成端口來異步完成的。

這樣做的好處就是:如果短時(shí)間內(nèi)客戶端并發(fā)連接請(qǐng)求不是很多,accept和AcceptEx在性能上區(qū)別不大,

雖然我們創(chuàng)建Socket只用一行SOCKET s =socket(...)一行代碼,但是系統(tǒng)內(nèi)部建立一個(gè)Socket是相當(dāng)

耗費(fèi)資源的,因?yàn)閃insock2是分層的機(jī)構(gòu)體系,創(chuàng)建一個(gè)Socket需要用到多個(gè)Provider之間進(jìn)行處理,

最終形成一個(gè)可用的套接字,總之,創(chuàng)建一個(gè)Socket的開心是相當(dāng)高的。

AcceptEx比Accept強(qiáng)三點(diǎn):

(1)最關(guān)鍵的是AcceptEx在客戶端連入之前,就把客戶端的Socket建立好了,也就是說,AcceptEx是先建立

Socket,然后發(fā)出的AcceptEx調(diào)用,也就是說,在進(jìn)行客戶端的通信之前,無論是否有客戶端連入,

Socket都是提前建立好的,而不需要想accept是在客戶端連入之后,在現(xiàn)場(chǎng)話費(fèi)時(shí)間建立Socket,

(2)相比Accept只能阻塞方式建立一個(gè)連入的入口,對(duì)于大量的并發(fā)客戶端來講,是在是有點(diǎn)擠,

而AcceptEx可以在完成端口上投遞多個(gè)請(qǐng)求,還有客戶端連入的時(shí)候,就非常優(yōu)雅而且從容.

(3)AcceptEx還有一個(gè)優(yōu)點(diǎn),就是投遞AccepEx的時(shí)候,收取客戶端發(fā)來的第一組數(shù)據(jù),這是同時(shí)

進(jìn)行的, 也就意味著,如果客戶端只是連入但不發(fā)送數(shù)據(jù)的話,我們就不會(huì)收到這個(gè)AccepeEx完成的通知,

異步的AcceptEx使用起來比accept要麻煩。



由于時(shí)間關(guān)系,在下篇博客 會(huì)詳細(xì)介紹完成端口的用法

實(shí)現(xiàn)圖片中的功能

Windows完成端口 IOCP模型(一)






參考博客地址 http://www.cnblogs.com/lancidie/archive/2011/12/19/2293773.html




向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI