Winsock完成埠介紹

2021-05-18 07:43:48 字數 3941 閱讀 7973

本文主要**一下windows平台上的完成埠開發及其與之相關的幾個重要的技術概念,這些概念都是與基於iocp的開發密切相關的,對開發人員來講,又不得不給予足夠重視的幾個概念:

1)基於iocp實現的服務吞吐量

2)iocp模式下的執行緒切換

3)基於iocp實現的訊息的亂序問題。

一、iocp簡介

提到iocp,大家都非常熟悉,其基本的程式設計模式,我就不在這裡展開了。在這裡我主要是把iocp中所提及的概念做乙個基本性的總結。iocp的基本架構圖如下:

如圖所示:在iocp中,主要有以下的參與者:

--》完成埠:是乙個fifo佇列,作業系統的io子系統在io操作完成後,會把相應的iopacket放入該佇列。

--》等待者執行緒佇列:通過呼叫getqueuedcompletionstatusapi,在完成埠上等待取下乙個iopacket。

--》執行者執行緒組:已經從完成埠上獲得iopacket,在占用cpu進行處理。

除了以上三種型別的參與者。我們還應該注意兩個關聯關係,即:

--》iohandle與完成埠相關聯:任何期望使用iocp的方式來處理io請求的,必須將相應的iohandle與該完成埠相關聯。需要指出的時,這裡的iohandle,可以是file的handle,或者是socket的handle。

--》執行緒與完成埠相關聯:任何呼叫getqueuedcompletionstatusapi的執行緒,都將與該完成埠相關聯。在任何給定的時候,該執行緒只能與乙個完成埠相關聯,與最後一次呼叫的getqueuedcompletionstatus為準。

二、高併發的伺服器(基於socket)實現方法

一般來講,實現基於socket的伺服器,有三種實現的方式(threadperrequest的方式,我就不提了:)):

一、執行緒池的方式。使用執行緒池來對客戶端請求進行服務。使用這種方式時,當客戶端對伺服器的連線是短連線(所謂的短連線,即:客戶端對伺服器不是長時間連線)時,是可以考慮的。但是,如若客戶端對伺服器的連線是長連線時,我們需要限**務器端的最大連線數目為執行緒池執行緒的最大數目,而這應用的設計本身來講,是不好的設計方式,scalability會存在問題。

二、基於select的伺服器實現。其本質是,使用select(作業系統提供的api)來監視連線是否可讀,可寫,或者是否出錯。相比於前一種方式,select允許應用使用乙個執行緒(或者是有限幾個執行緒)來監視連線的可讀寫性。當有連線可讀可寫時,應用可以以non-bolock的方式讀寫socket上的資料。使用select的方式的缺點是,當select所監視的連線數目在千的數量級時,效能會打折扣。這是因為作業系統核心需要在內部對這些socket進行輪詢,以檢查其可讀寫性。另乙個問題是:應用必須在處理完所有的可讀寫socket的io請求之後,才能再次呼叫select,進行下一輪的檢查,否則會有潛在的問題。這樣,造成的結果是,對一些請求的處理會出現飢餓的現象。

一般common的做法是select結合leader-follower設計模式使用。不過不管怎樣,select的本質造成了其在scalability的問題是不如iocp,這也是很多high-scalabe的伺服器採用iocp的原因。

第三、iocp實現高併發的伺服器。iocp是實現high-scalabe的伺服器的首選。其特點我們專門在下一小姐陳述。

三、iocp開發的幾個概念

一、伺服器的吞吐量問題。

我們都知道,基於iocp的開發是非同步io的,也正是這一技術的本質,決定了iocp所實現的伺服器的高吞吐量。

我們舉乙個及其簡化的例子,來說明這一問題。在網路伺服器的開發過程中,影響其效能吞吐量的,有很多因素,在這裡,我們只是把關注點放在兩個方面,即:網路io速度與diskio速度。我們假設:在乙個千兆的網路環境下,我們的網路傳輸速度的極限是大概125m

/s,而diskio的速度是10m

/s。在這樣的前提下,慢速的disk裝置會成為我們整個應用的瓶頸。我們假設執行緒a負責從網路上讀取資料,然後將這些資料寫入disk。如果對disk的寫入是同步的,那麼執行緒a在等待寫完disk的過程是不能再從網路上接受資料的,在寫入disk的時間內,我們可以認為這時候server的吞吐量為0(沒有接受新的客戶端請求)。對於這樣的同步讀寫disk,一些的解決方案是通過增加執行緒數來增加伺服器處理的吞吐量,即:當執行緒a從網路上接受資料後,驅動另外單獨的執行緒來完成讀寫disk任務。這樣的方案缺點是:需要執行緒間的合作,需要執行緒間的切換(這是另乙個我們要討論的問題)。而iocp的非同步io本質,就是通過作業系統核心的支援,允許執行緒a以非阻塞的方式向io子系統投遞io請求,而後馬上從網路上讀取下乙個客戶端請求。這樣,結果是:在不增加執行緒數的情況下,iocp大大增加了伺服器的吞吐量。說到這裡,聽起來感覺很像是dma。的確,許多軟體的實現技術,在本質上,與硬體的實現技術是相通的。另外乙個典型的例子是硬體的流水線技術,同樣,在軟體領域,也有很著名的應用。好像話題扯遠了,呵呵:)

二、執行緒間的切換問題。

伺服器的實現,通過引入iocp,會大大減少thread切換帶來的額外開銷。我們都知道,對於伺服器效能的乙個重要的評估指標就是:system/contextswitches,即單位時間內線程的切換次數。如果在每秒內,執行緒的切換次數在千的數量級上,這就意味著你的伺服器效能值得商榷。contextswitches/s應該越小越好。說到這裡,我們來重新審視一下iocp。

完成埠的執行緒併發量可以在建立該完成埠時指定(即numberofconcurrentthreads引數)。該併發量限制了與該完成埠相關聯的可執行執行緒的數目(就是前面我在iocp簡介中提到的執行者執行緒組的最大數目)。當與該完成埠相關聯的可執行執行緒的總數目達到了該併發量,系統就會阻塞任何與該完成埠相關聯的後續執行緒的執行,直到與該完成埠相關聯的可執行執行緒數目下降到小於該併發量為止。最有效的假想是發生在有完成包在佇列中等待,而沒有等待被滿足,因為此時完成埠達到了其併發量的極限。此時,乙個正在執行中的執行緒呼叫getqueuedcompletionstatus時,它就會立刻從佇列中取走該完成包。這樣就不存在著環境的切換,因為該處於執行中的執行緒就會連續不斷地從佇列中取走完成包,而其他的執行緒就不能執行了。

完成埠的執行緒併發量的建議值就是你系統cpu的數目。在這裡,要區分清楚的是,完成埠的執行緒併發量與你為完成埠建立的工作者執行緒數是沒有任何關係的,工作者執行緒數的數目,完全取決於你的整個應用的設計(當然這個不宜過大,否則失去了iocp的本意:))。

第三、iocp開發過程中的訊息亂序問題。

使用iocp開發的問題在於它的複雜。我們都知道,在使用tcp時,tcp協議本身保證了訊息傳遞的次序性,這大大降低了上層應用的複雜性。但是當使用iocp時,問題就不再那麼簡單。如下例:

三個執行緒同時從iocp中讀取msg1,msg2,與msg3。由於tcp本身訊息傳遞的有序性,所以,在iocp佇列內,msg1-msg2-msg3保證了有序性。三個執行緒分別從iocp中取出msg1,msg2與msg3,然後三個執行緒都會將各自取到的訊息投遞到邏輯層處理。在邏輯處理層的實現,我們不應該假定msg1-msg2-msg3順序,原因其實很簡單,在time1~time2的時間段內,三個執行緒被作業系統排程的先後次序是不確定的,所以在到達邏輯處理層,

msg1,msg2與msg3的次序也就是不確定的。所以,邏輯處理層的實現,必須考慮訊息亂序的情況,必須考慮多執行緒環境下的程式實現。

在這裡,我把訊息亂序的問題單列了出來。其實在iocp的開發過程中,相比於同步的方式,應該還有其它更多的難題需要解決,這也是與select方式相比,iocp的缺點,實現複雜度高。

結束語:

ace的proactorframework,對windows平台的iocp做了基於proactor設計模式的,物件導向的封裝,這在一定程度上簡化了應用開發的難度,是乙個很好的非同步io的開發框架,推薦學習使用。

reference:

microsofttechnet,insidei/ocompletionports

Winsock 完成埠類分析(一)

在windows 下進行網路服務端程式開發,毫無疑問,winsock 完成埠模型是最高效的。winsock的完成埠模型借助widnows的重疊io和完成埠來實現,完成埠模型懂了之後是比較簡單的,但是要想掌握winsock完成埠模型,需要對windows下的執行緒 執行緒同步,winsock api以...

完成埠模型

最近要做乙個網路方面的小東東,基於c s模式的。都說iocp可以使系統達到最佳的效能,因此我就比劃了兩下,獻醜了。抄書開始。從本質上說,完成埠模型要求建立乙個windows完成埠物件,該物件通過指定數量的執行緒,對重疊i o請求進行管理,以便為已經完成的重疊i o請求提供服務。首先要建立乙個i o完...

完成埠iocp和重疊埠

windows下的iocp和 linux下的epoll epoll我還沒有研究過 都是屬於socket 網路程式設計的範疇.不過其特色是 用固定很少的執行緒去管理成千上萬個socket連線.其相當於 非同步通訊 普通socket是同步,同步 可能要乙個執行緒乙個socket鏈結 去做,由於系統可以執...