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系统。