最近在测试IOCP模型的UDP通讯中发现,如果服务端UDP套接字直接给某个客户端发送数据,而该客户端不存在,会导致
上面的GetQueuedCompletionStatus会被激活,但返回错误,数据大小为0,
而且再投递WSARecvFrom请求,即使没有客户端发送数据,也会立即收到GetQueuedCompletionStatus
返回的错误消息,最终导致再也无法接收客户端数据,经过分析,可以用下面的方式解决该类问题。
若要解决此问题,获得最新的 service pack,对于 Windows 2000。有关详细的信息请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
在 Windows 2000 引入了新的套接字 IOCTL 称为"SIO_UDP_CONNRESET"。专门为获取原始的 Windows NT 4.0 的 Windows 2000 在使用此 IOCTL 时必须重写该程序的行为。Windows NT 4.0、 Microsoft Windows 95,和 Microsoft Windows 98 具有不支持此新 IOCTL。除了重写应用程序,您将需要引用该修补程序在本文中进一步。
下面的代码段演示一种技术,它可用于获取原始的 Windows NT 4.0 行为 SIO_UDP_CONNRESET 控件代码中调用 WSAIoctl
DWORDdwBytesReturned = 0;
BOOLbNewBehavior = FALSE;
DWORDstatus;
// disable new behavior using
// IOCTL: SIO_UDP_CONNRESET
status = WSAIoctl(sd, SIO_UDP_CONNRESET,
&bNewBehavior, sizeof(bNewBehavior),
NULL, 0, &dwBytesReturned,
NULL, NULL);
if (SOCKET_ERROR == status)
{
DWORD dwErr = WSAGetLastError();
if (WSAEWOULDBLOCK == dwErr)
{
// nothing to do
return(FALSE);
}
else
{
printf("WSAIoctl(SIO_UDP_CONNRESET) Error: %d/n", dwErr);
return(FALSE);
}
}
要对其进行编译此代码,您需要具有在最新 Mswsock.h,其中包括 SIO_UDP_CONNRESET 的定义,或定义它的直接向代码在下方插入
// MS Transport Provider IOCTL to control
// reporting PORT_UNREACHABLE messages
// on UDP sockets via recv/WSARecv/etc.
// Path TRUE in input buffer to enable (default if supported),
// FALSE to disable.
#defineSIO_UDP_CONNRESET_WSAIOW(IOC_VENDOR,12)
注意 本文中介绍的修补程序不会解决此问题,除非该程序会使用新的 SIO_UDP_CONNRESET IOCTL 被重写。