WSADuplicateSocket、WSASocket失敗,錯誤碼為WSAEINVAL(10022)
PS:最近又發現一種無法複用套接字的情況,修改一下。2011/10/11 16:24
一、失敗的原因:
1、MS的解釋
http://support.microsoft.com/kb/216603/en-us
2、目標程序和當前程序不在同一個session內
3、當前程序許可權比目標程序低
WSADuplicateSocket內部會呼叫OpenProcess開啟目標程序的控制代碼,如果當前程序許可權較低,將會導致失敗,最終返回10022.
4、套接字的接收緩衝區大小不是預設值,且大於等於65536。
這種情況會導致WSADuplicateSocket失敗,或者WSADuplicateSocket成功但WSASocket失敗。
二、解決方案:
1、第一種情況,攔截WSASocket, WSPSocket, WSAConnect,將WSAPROTOCOL_INFOW的dwServiceFlages1欄位進行如下處理:
WSAPROTOCOL_INFOW lpProtocolInfo;
lpProtocolInfo.dwServiceFlages1 &= ~XP1_QOS_SUPPORTED。
以上程式碼防止當前程序建立QOS-enable套接字,保證WSADuplicateSocket成功。
2、第二種情況,不懂。
3、攔截OpenProcess,在內部返回目標程序的控制代碼。如何得到目標程序控制代碼是個難點。不過目標程序往往是自己寫,所以可以通過訊息機制讓目標程序呼叫DuplicateHandle返回它的控制代碼。
4、設定套接字的接收緩衝區時,大小小於65536即可。
這個情況是遨遊的工程師在一段原始碼的註釋中發現的,原始碼地址:http://www.oschina.net/code/explore/cygwin-1.7.7-1/winsup/cygwin/net.cc。只有以下三個條件同時成立時,接收緩衝區的大小才會導致客戶端進行套接字複用時失敗:
a. 服務端和客戶端處於不同機器;
b. 客戶端已經收到一部分資料時;
c. xp系統。