前言在windows平台下實現高效能網路伺服器,iocp(完成埠)是唯一選擇。編寫網路伺服器面臨的問題有:1 快速接收客戶端的連線。2 快速收發資料。3 快速處理資料。本文主要解決第乙個問題。
acceptex函式定義
bool acceptex(
socket slistensocket,
socket sacceptsocket,
pvoid lpoutputbuffer,
dword dwreceivedatalength,
dword dwlocaladdresslength,
dword dwremoteaddresslength,
lpdword lpdwbytesreceived,
);
為什麼要用acceptex
傳統的accept函式能滿足大部分場景的需要;但在某些極端條件下,必須使用acceptex來實現。兩個函式的區別如下:
1)accept是阻塞的;在乙個埠監聽,必須啟動乙個專用線程呼叫accept。當然也可以用迂迴的方式,繞過這個限制,處理起來會很麻煩,見文章單執行緒實現同時監聽多個埠。acceptex是非同步的,可以同時對很多埠監聽(監聽埠的數量沒有上限的限制)。採用迂迴的方式,使用accept監聽,乙個執行緒最多監聽64個埠。這一點可能不是acceptex最大優點,畢竟同時對多個埠監聽的情況非常少見。
2)acceptex可以返回更多的資料。a)acceptex可以返回本地和對方ip位址和埠;而不需要呼叫函式getsockname和getpeername獲取網路位址了。b)acceptex可以再接收到一段資料後,再返回。這種做法有利有弊,一般不建議這樣做。
3)acceptex是先準備套接字(socket)後接收。為了應對突發的連線高峰,可以多次投放acceptex。accept是事後建立socket,就是tcp三次握手完成後,accept呼叫才返回,再生成socket。生成套接字是相對比較耗時的操作,accept的方式無法及時處理突發連線。對於acceptex的處理方式為建議做如下處理:乙個執行緒負責建立socket,乙個執行緒負責處理acceptex返回。
以上僅僅通過文字說明了acceptex的特點。下面通過具體**,逐一剖析。我將acceptex的處理封裝到類iocpacceptex中。編寫該類時,盡量做到高內聚低耦合,使該類可以方便的被其他模組使用。
iocpacceptex外部功能說明
class iocpacceptex
#define post_accept 1
//使用iocpacceptex類,必須實現該介面。接收客戶端的連線
class iacceptcallback
;
該類的呼叫函式很簡單,對外介面也很明確。說明該類的職責很清楚,這也符合單一職責原則。
實現步驟說明
acceptex不但需要與監聽埠繫結,還需要與完成埠繫結。所以程式的第一步是建立完成埠:
a)建立完成埠
m_hiocp = createiocompletionport(invalid_handle_value, null, null, 0);
if (m_hiocp == null)
return false;
b)監聽埠建立與繫結
//生成套接字
if (serversocket == invalid_socket)
//繫結
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = af_inet;
addr.sin_addr.s_addr = inaddr_any ;
addr.sin_port = htons(port);
if (bind(serversocket, (sockaddr *)&addr, sizeof(addr)) != 0)
//啟動監聽
if (listen(serversocket, somaxconn) != 0)
//監聽埠與完成埠繫結
if (createiocompletionport((handle)serversocket, m_hiocp, (ulong_ptr)this, 0) == null)
c)投遞acceptex
;int iocpacceptex::newaccept(socket serversocket)
}return 1;}
acceptex是非阻塞操作,呼叫會立即返回。當有客戶端連線時,怎麼得到通知。答案是通過完成埠返回。注意有乙個步驟:監聽埠與完成埠繫結,就是serversocket與m_hiocp繫結,所以當有客戶端連線serversocket時,m_hiocp會得到通知。需要生成執行緒,等待完成埠的通知。
d)通過完成埠,獲取通知
dword dwbytestransferred;
ulong_ptr key;
bool rc;
int error;
while (m_bserverstart)
else}}
if (lpperiodata != null)
break;}}
else
}return 0;
dword winapi iocpacceptex::acceptexthreadpool(pvoid pcontext)
** 採用完成埠是提高io處理能力的乙個途徑(廣義上講,通訊操作也是io)。為了提高io處理能力,windows提供很多非同步操作函式,這些函式都與完成埠關聯,所以這一類處理的思路基本一致。學會了acceptex的使用,可以做到觸類旁通的效果。 AcceptEx函式與完成埠的結合使用例子
這是在學 windows網路程式設計 第二版 第六章時製作的乙個例子 由於書中沒有給出簡潔的例子,本人在學這裡時就費了很多時間。下面包括了主程式部分,工作執行緒在 2 中貼出,由於 太長。本程式在vs2003編譯器編譯執行。在6.0下可能需要稍加修改。include include include ...
完成埠IO模型
iocp io完成埠 是一種伸縮性的io模型,廣泛應用於各種型別的高效能伺服器,如apache等。io完成埠,應用程式使用執行緒池處理非同步io請求的一種機制。最初設計 應用程式發出一些非同步io請求,裝置驅動把這些工作專案排序到完成埠,在完成埠上等待執行緒池便可以處理這些完成io。完成埠實際上是乙...
I O 完成埠實現
這篇文章是繼承上篇 windows 同步裝置 i o 與非同步裝置 i o 未讀過的讀者可以去看看再來看這篇文章哈。建立新的i o完成埠 i o完成可能是最複雜的windows核心物件了,為了建立乙個i o完成端 們需要呼叫createiocompletionport函式 handle winapi...