http://h-lm.spaces.live.com/blog/cns!C523F565A10E3B66!824.entry
實現UDP IOCP心得
通宵奮戰,搞定UDP+IOCP
{
OVERLAPPED Overlapped;
WSABUF DataBuff;
char Buff[24];
BOOL OperationType;
}PER_IO_OPERATION_DATA,* LPPER_IO_OPERATION_DATA;
{
OVERLAPPED Overlapped;
WSABUF DataBuff;
char Buff[24];
unsigned long recvBytes; //存儲接收到的字節數
SOCKADDR_IN remoteAddr; //存儲數據來源IP地址
int remoteAddrLen; //存儲數據來源IP地址長度
}PER_IO_OPERATION_DATA,* LPPER_IO_OPERATION_DATA;
ioperdata = (LPPER_IO_OPERATION_DATA)malloc(sizeof(PER_IO_OPERATION_DATA));
memset(&(ioperdata->Overlapped), 0, sizeof(OVERLAPPED));
(ioperdata->DataBuff).len = 24;
(ioperdata->DataBuff).buf = ioperdata->Buff;
ioperdata->recvBytes = 24;
ioperdata->remoteAddrLen = sizeof(ioperdata->remoteAddr);
(HANDLE)udpSocket,
hCompletionPort,
(DWORD)udpSocket,
5
);
udpSocket, &BytesTransferred,
&(ioperdata->DataBuff), (LPDWORD) & nSocket,
1, (LPOVERLAPPED *) & PerIoData,
&(ioperdata->recvBytes), INFINITE );
&flags,
(SOCKADDR*) & (ioperdata->remoteAddr),
&(ioperdata->remoteAddrLen),
&(ioperdata->Overlapped),
NULL); 處理接收到的數據
2- 不要試圖在發送出IOCP請求之後,收到完成通知之前修改請求中使用的數據緩衝的內容,因爲在這段時間,系統可能會來讀取這些緩衝.
3- 爲了避免內存拷貝,可以嘗試關閉SOCKET的發送和接收緩衝區,不過代價是,你需要更多的接收請求POST到一個數據流量比較大的SOCKET,從而保證系統一直可以找到BUFFER來收取到來的數據.
4- 在發出多個接收請求的時候,如果你的WORKTHREAD不止一個,一定要使用一些手段來保證接收完成的數據按照發送接收請求的順序處理,否則,你會遇到數據包用混亂的順序排列在你的處理隊列裏.....
5- 說起工作線程, 最好要根據MS的建議, 開 CPU個數*2+2 個, 如果你不瞭解IOCP的工作原理的話.
6- IOCP的工作線程是系統優化和調度的, 自己就不需要進行額外的工作了.如果您自信您的智慧和經驗超過MS的工程師, 那你還需要IOCP麼....
7-發出一個Send請求之後,就不需要再去檢測是否發送完整,因爲iocp會幫你做這件事情,有些人說iocp沒有做這件事情,這和iocp的高效能是相悖的,並且我做過的無數次測試表明,Iocp要麼斷開連接,要麼就幫你把每個發送請求都發送完整。
8- 出現數據錯亂的時候,不要慌,要從多線程的角度檢查你的解析和發送數據包的代碼,看看是不是有順序上的問題。
9- 當遇到奇怪的內存問題時,逐漸的減少工作線程的數量,可以幫你更快的鎖定問題發生的潛在位置。
10-同樣是遇到內存問題時,請先去檢查你的客戶端在服務器端內部映射對象的釋放是否有問題。而且要小心的編寫iocp完成失敗的處理代碼,防止引用一個錯誤的內部映射對象的地址。
11- overlapped對象一定要保存在持久的位置,並且不到操作完成(不管成功還是失敗)不要釋放,否則可能會引發各種奇怪的問題。
12- IOCP的所有工作都是在獲取完成狀態的那個函數內部進行調度和完成的,所以除了注意工作線程的數量之外,還要注意,儘量保持足夠多的工作線程處在獲取完成狀態的那個等待裏面,這樣做就需要減少工作線程的負擔,確保工作線程內部要處理費時的工作。(我的建議是工作線程和邏輯線程徹底區分開)
13- 剛剛想起來,overlapped對象要爲每次的send和recv操作都準備一個全新的,不能圖方便重複利用。
14- 儘量保持send和recv的緩衝的大小是系統頁面大小的倍數,因爲系統發送或者接收數據的時候,會鎖用戶內存的,比頁面小的緩衝會浪費掉整個一個頁面。(作爲第一條的補充,建議把小包合併成大包發送)