WinSock recvfrom/WSARecvFrom返回WSAECONNRESET(10054)解决

 当在使用UDP的时候,如果碰到recvfrom/WSARecvFrom返回WSAECONNRESET(10054)时,需要注意。问题的描述可见(www-pc.uni-regensburg.de/systemsw/W2KPRO/UPDATE/POSTSP1/Q263823.htm),详细内容如下:

SYMPTOMS

In Windows 2000, a User Datagram Protocol (UDP) program may not work and may generate a WSAECONNRESET response.

 

CAUSE

If sending a datagram using the sendto function results in an "ICMP port unreachable" response and the select function is set for readfds, the program returns 1 and the subsequent call to the recvfrom function does not work with a WSAECONNRESET (10054) error response. In Microsoft Windows NT 4.0, this situation causes the select function to block or time out.

 

RESOLUTION

A new sockets IOCTL called "SIO_UDP_CONNRESET" has been introduced in Windows 2000. When this IOCTL is used, the program must be rewritten specifically for Windows 2000 to obtain the original Windows NT 4.0 behavior. Windows NT 4.0, Microsoft Windows 95, and Microsoft Windows 98 have no support for this new IOCTL. In addition to rewriting your application, you will need the hotfix referenced further down in this article.

The following code snippet demonstrates a technique that can be used to call WSAIoctl with the SIO_UDP_CONNRESET control code to obtain the original Windows NT 4.0 behavior:

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);
}
}

To be able to compile this code, you need either to have the latest Mswsock.h which includes the definition of SIO_UDP_CONNRESET or to insert below definition of it directly into your code:

// 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)

NOTE: The hotfix that is described in this article will not resolve the problem unless the program is rewritten to use the new SIO_UDP_CONNRESET IOCTL.

For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

Q263823 WinSock Recvfrom() Now Returns WSAECONNRESET Instead of Blocking or Timing Out

STATUS

Microsoft has confirmed this to be a problem in the Microsoft products listed at the beginning of this article

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Windows 平台上,`recvfrom` 函数在发生错误时会返回 `-1`。此时,可以使用 `WSAGetLastError` 函数获取错误码,然后根据错误码进行调试和处理。 以下是一个简单的示例代码,可以用来测试 `recvfrom` 函数的返回值: ```c++ #include <winsock2.h> #include <iostream> #define BUF_SIZE 1024 int main() { // 初始化 WinsockWSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "Failed to initialize Winsock." << std::endl; return 1; } // 创建套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock == INVALID_SOCKET) { std::cerr << "Failed to create socket." << std::endl; WSACleanup(); return 1; } // 绑定端口 sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(1234); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { std::cerr << "Failed to bind socket." << std::endl; closesocket(sock); WSACleanup(); return 1; } // 接收数据 char buf[BUF_SIZE]; sockaddr_in clientAddr; int clientAddrLen = sizeof(clientAddr); int recvLen = recvfrom(sock, buf, BUF_SIZE, 0, (sockaddr*)&clientAddr, &clientAddrLen); if (recvLen == SOCKET_ERROR) { int errCode = WSAGetLastError(); std::cerr << "Failed to receive data: " << errCode << std::endl; closesocket(sock); WSACleanup(); return 1; } // 输出接收到的数据 buf[recvLen] = '\0'; std::cout << "Received data: " << buf << std::endl; // 关闭套接字 closesocket(sock); WSACleanup(); return 0; } ``` 如果 `recvfrom` 函数返回 `-1`,则可以根据错误码进行调试和处理。常见的错误码包括: - `WSAECONNRESET`:连接被重置,通常是对方已经关闭了连接。 - `WSAEINTR`:函数被信号中断。 - `WSAEINVAL`:参数无效。 - `WSAEMSGSIZE`:接收到的消息太大,无法放入缓冲区。 - `WSAEWOULDBLOCK`:套接字处于非阻塞模式,没有数据可用。 - `WSANOTINITIALISED`:未初始化 Winsock 库。 根据具体的错误码,可以采取不同的处理方式,例如重新尝试接收数据、关闭套接字等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值