WinSock中关于阻塞接收/发送超时的一个BUG

在阻塞模型中,recvfrom和recv函数默认都是永久阻塞的,即没有数据到来和不发生错误的情况下函数的调用不会返回,但是可以调用setsockopt来设置阻塞时间。设置了合适的阻塞时间,可以让接收函数超时返回。

  1. int setsockopt(  
  2.   __in          SOCKET s,  
  3.   __in          int level,  
  4.   __in          int optname,  
  5.   __in          const char* optval,  
  6.   __in          int optlen  
  7. );  
SO_RCVTIMEOintReceives time-out in milliseconds (available in the Microsoft implementation of Windows Sockets 2).
SO_SNDTIMEOintSends time-out in milliseconds (available in the Microsoft implementation of Windows Sockets 2).

SO_RECVTIMEO即可控制接收函数的超时时间。例代码如下:

  1. #include <WinSock2.h>  
  2. #include <Windows.h>  
  3. #include <stdio.h>  
  4. #include <time.h>  
  5.   
  6. #pragma comment(lib, "Ws2_32.lib")  
  7.   
  8. int main()  
  9. {  
  10.     WSADATA wd;  
  11.   
  12.     WSAStartup(MAKEWORD(2, 2), &wd);  
  13.   
  14.     SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  
  15.   
  16.     sockaddr_in sin;  
  17.     DWORD dwTime = 1000;  
  18.   
  19.     sin.sin_family = AF_INET;  
  20.     sin.sin_addr.s_addr = INADDR_ANY;  
  21.     sin.sin_port = htons(0);  
  22.   
  23.     if (SOCKET_ERROR == bind(sock, (sockaddr *)&sin, sizeof(sin)) ||  
  24.         SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&dwTime, sizeof(dwTime)))  
  25.     {  
  26.         return 0;  
  27.     }  
  28.   
  29.     DWORD dwIndex = 0;  
  30.   
  31.     while (TRUE)  
  32.     {  
  33.         char szBuffer[10000];  
  34.         int len = sizeof(sin);  
  35.         int nRet = recvfrom(sock, szBuffer, sizeof(szBuffer), 0, (sockaddr *)&sin, &len);  
  36.   
  37.         //本应至少每一秒输出一次,但是将系统时间更改到之前的时间后,此处不再输出  
  38.         printf("%lu::%lu:%d\n", dwIndex++, time(NULL), nRet);  
  39.     }  
  40.   
  41.     closesocket(sock);  
  42.   
  43.     return 0;  
  44. }  

设定了超时时间后,recvfrom会定期返回并输出消息,如果这时候更改了系统时间,比如把系统时间改为昨天,那么recvfrom就不会立即返回了。把系统时间向后改比如改为明天则没有这个问题,但是再改回来又会出问题。推测是内部实现使用了绝对时间,而非相对时间才导致了这个问题。

阻塞IO模型中的UDP发送、TCP接收、TCP发送应该也存在类似的问题,不过我没有进行测试。linux平台不存在这个问题。

ps:我认为linux平台的做法是对的,这里应当使用相对时间。


转自:http://blog.csdn.net/my3439955/article/details/8909216

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值