Socket中如何设置连接超时(转)

http://tangfeng.iteye.com/blog/795497

Socket中可以使用select设置连接超时,需要先将socket设置为非锁定模式,这样,在connect时,才会立马跳过,同时,通常也会产生一个WSAEWOULDBLOCK错误,这个错误没关系。再执行select则是真正的超时。 

C++代码  收藏代码
  1.    
  2. WSADATA wsd;     
  3. SOCKET cClient;     
  4. int ret;     
  5. struct sockaddr_in server;     
  6. hostent *host = NULL;     
  7.     
  8. if (WSAStartup(MAKEWORD(2,0), &wsd))     
  9. {    
  10.     return 0;    
  11. }    
  12. cClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);     
  13. if (cClient == INVALID_SOCKET)     
  14. {    
  15.     return 0;    
  16. }     
  17.     
  18. // set Recv and Send time out     
  19. DWORD TimeOut = 6000; // 设置发送超时6秒     
  20. if (::setsockopt(cClient, SOL_SOCKET, SO_SNDTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)     
  21. {     
  22.     return 0;     
  23. }     
  24.     
  25. TimeOut = 6000; // 设置接收超时6秒     
  26. if (::setsockopt(cClient, SOL_SOCKET, SO_RCVTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)     
  27. {     
  28.     return 0;     
  29. }     
  30.     
  31. // 设置非阻塞方式连接     
  32. unsigned long ul = 1;     
  33. ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);     
  34. if (ret == SOCKET_ERROR)    
  35.     return 0;     
  36.     
  37. // 连接     
  38. server.sin_family = AF_INET;     
  39. server.sin_port = htons(25);    
  40. server.sin_addr.s_addr = inet_addr((LPCSTR)pSmtp);     
  41. if (server.sin_addr.s_addr == INADDR_NONE)    
  42.     return 0;    
  43.     
  44. connect(cClient, (const struct sockaddr*)&server, sizeof(server));     
  45.     
  46. // select 模型,即设置超时     
  47. struct timeval timeout ;     
  48. fd_set r;     
  49. FD_ZERO(&r);     
  50. FD_SET(cClient, &r);     
  51. timeout.tv_sec = 15; // 连接超时15秒     
  52. timeout.tv_usec = 0;     
  53. ret = select(0, 0, &r, 0, &timeout);     
  54. if (ret <= 0)    
  55. {    
  56.     ::closesocket(cClient);     
  57.     return 0;     
  58. }    
  59.     
  60. // 一般非锁定模式套接字比较难控制,可以根据实际情况考虑再设回阻塞模式     
  61. unsigned long ul1 = 0;     
  62. ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);    
  63. if (ret == SOCKET_ERROR)    
  64. {     
  65.     ::closesocket(cClient);     
  66.     return 0;    
  67. }  
posted @ 2011-06-28 10:34  董雨  阅读(310)  评论(0编辑  收藏  举报