IO完成埠(IOCP)

IO完成埠(IOCP)

1 人贊了文章

1 概述

IO完成埠是windows下性能最好的IO模型。

windows下的socket也是一種IO,所以完成埠也是最好的socket IO模型。

不幸的是,IO完成埠非常複雜,理解它門檻已經非常很高,而正確使用的門檻比理解它還要高很多。

之所以這麼難理解,很大原因也在於沒有好的資料。MSDN的文檔已經相當良心的完善,但是還是有許多的問題沒有解釋清楚,整個模型的機制模糊不清。而網上的文檔只能作為入門,裡面的內容離實際可用的代碼有十萬八千里那麼遠,比如很多的文檔連發送的功能都沒有講到。至於udp使用iocp,就更少有資料了。

2 簡化模型圖

這個最簡單的模型,用來表示IOCP涉及到的對象。

這裡有三個對象,主線程,socket工作線程,系統API模塊。

上面是用戶代碼層,下面是系統的IOCP API層。主線程和工作線程都處於用戶代碼層。

3 簡化流程圖

這個最簡單的流程圖,表示了主線程和Socket工作線程的主要流程。

簡單的描敘一下:

(1)主線程通常是消息循環線程。主線程調用系統IOCP API發起操作(如WSARecv開始收Socket數據),請求系統完成該操作。

(2)系統收到操作請求,進行處理(如開始收Socket數據),並在處理完成時(如收到了60K數據),發出事件,事件會喚醒工作線程。

(3)工作線程通常是普通線程。阻塞等待事件,處理事件,並發送消息通知主線程(如"收到60K的Socket數據消息")。

(4)主線程收到消息,處理消息(如"收到60K的Socket數據消息"),處理業務邏輯(比如在界面上顯示:你收到一條新的消息)。

4 模型要素

4.1 非同步操作

非同步操作是一個函數,該函數立即返回,作用是請求系統完成一些事情,系統經過一段時間完成了,就觸發一個系統事件,喚醒等待事件的線程。

非同步操作有:WSASend(發送數據),WSARecv(接受數據),PostQueuedCompletionStatus(發自定義事件)。

4.2 系統事件

系統事件有:Socket事件(發送SOCKET數據完成事件,收到數據事件,SOCKET斷開連接事件),自定義事件:通過PostQueuedCompletionStatus發送的事件。

4.3 主線程

主線程通常是業務邏輯的所在,我們這裡假設主線程是消息循環線程。

主線程建立和銷毀工作線程,建立的過程很簡單,這裡略去,銷毀的時候,是通過發送一個事件給工作線程,工作線程被喚醒並處理事件,退出。

主線程可以調用系統IOCP函數(如WSARecv函數接受Socket數據),該函數立即返回,不阻塞主線程。

主線程會收到工作線程發過來的消息(例如收到數據消息)。

4.4 工作線程

工作線程通常不做複雜的業務邏輯,是一個普通線程。

工作線程阻塞等待系統事件(GetQueuedCompletionStatus),每當收到系統事件,就會被喚醒,然後簡單處理事件:例如把收到的Socket數據包裝成一個消息,發送給主線程。

5 事件和操作

5.1 事件和操作之間基本關係

(1)只有發出操作,才可能收到事件。不發出操作,不會收到事件。

(2)發出一個操作,收到一個事件。

5.2 WSARecv操作

有可能收到「SOCKET收到數據事件」,「SOCKET斷開連接事件」。

調用WSARecv函數

(1)如果系統之前已經接收了Socket數據:

函數返回值為0,函數的出參里已經有收到的Socket數據了,但是,阻塞等待的線程依然會收到事件,事件的參數裡面也帶有Socket數據。

(2)如果系統之前沒有接收到Socket數據:

函數返回值不為0,如果WSAGetLastError為WSA_IO_PENDING時,表示投遞該操作給系統成功,阻塞等待的線程會收到事件(該事件有可能表示真的收到了數據,也可能是收數據失敗)。

5.3 WSASend操作

有可能收到「SOCKET發送數據完成事件」,「SOCKET斷開連接事件」。

當收到「發送數據完成事件」,並不代表數據真的發送完成,可能實際上只發了一部分,對方只收到一部分。

6 實際模型

實際的伺服器模型更加複雜,這個圖還是簡化了的,沒有畫上accept部分。

圖中,網路模塊和邏輯模塊都屬於用戶層代碼。

系統API模塊有兩個socket IO線程,一般來說,系統API層的線程數為:CPU數目*2。

網路模塊有四個SOCKET工作線程。一般來說,用戶層的SOCKET工作線程數為:CPU數目*4。


推薦閱讀:

我讀過的最好的epoll講解
《計算機網路:自頂向下方法》第二章配套實驗
不走心
C# Socket編程基礎入門
網路通信引擎007. 用Socket API 6步建立TCP服務端

TAG:設計模式 | Socket | 網路編程 |