Window+TCP+connect 超时阻塞解决办法
现象:一般情况下,connect是以阻塞模式进行工作的,但如果在S/C架构开发中,如果S端没有开启,而C端去connect一个未开启或不存在的S时,就
会出现“卡死”的现象。
原因:
客户端在连接服务器时,可能会出现问题,导致三次握手无法完成,持续重试,表现在客户端程序的行为就是卡在connect调用上无法返回。在一个
TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未完成;同时TCP的三路握手操作
继续进行;在这之后,我们可以调用select来检查这个链接是否建立成功;
解决方法:
1.建立socket
2.将该socket设置为非阻塞模式
3.调用connect()
4. 判断返回值是否是WSAEWOULDBLOCK,(在vs2015或linux下,应该是EINPROGRESS,没有试)
5.如果4成立,使用select()检查该socket描述符是否可写
6.如果5成立,则说明连接成功,将socket重设置为阻塞模式
附,网上还有一种说法是,第5步使用getsockopt来获取错误,如果不存在错误(错误值为0),则连接成功,但本人没有成功。
VC6++参考代码
1 int SKTCPSocket::connectHost(char *ip, const unsigned int port)
2 {
3 int ret=0;
4 timeval tm={2,0};
5 fd_set rset;
6 fd_set wset;
7 unsigned long mode = 1;
8
9 SOCKADDR_IN addrSrv;
10 addrSrv.sin_addr.S_un.S_addr = inet_addr(ip);
11 addrSrv.sin_family = AF_INET;
12 addrSrv.sin_port = htons(port);
13
14 mode = 1;
15 ret=ioctlsocket(m_clientSocket, FIONBIO, &mode); /*!<设置为非阻塞模式,成功返回0 */
16 if(ret)
17 {
18 closesocket(m_clientSocket);
19 return -1;
20 }
21
22 ret=connect(m_clientSocket, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));/*!<成功返回0,但在非阻塞情况下,一般为-1*/
23 if(ret)
24 {
25 ret=WSAGetLastError();
26 if(WSAEWOULDBLOCK==ret)/*!<如果Resource temporarily unavailable.10035*/
27 {
28 FD_ZERO(&rset);
29 FD_ZERO(&wset);
30 FD_SET(m_clientSocket, &rset);
31 FD_SET(m_clientSocket, &wset);
32
33 ret=select(m_clientSocket+1, &rset, &wset, NULL, &tm) ;
34 if(ret<0)
35 {
36 closesocket(m_clientSocket);
37 return -2;
38 }
39 else if(ret==0)/*!<Time Out*/
40 {
41 closesocket(m_clientSocket);
42 return -3;
43 }
44 else
45 {
46 if(FD_ISSET(m_clientSocket,&wset))/*!<如果可写,说明连接好*/
47 {
48 mode = 0;
49 ret=ioctlsocket(m_clientSocket, FIONBIO, &mode); /*!<再次设置为阻塞模式 */
50 if(ret)
51 {
52 closesocket(m_clientSocket);
53 return -4;
54 }
55 /*!<正确退出*/
56 return 0;
57 }
58 else
59 {
60 /*!<不可写*/
61 closesocket(m_clientSocket);
62 return -5;
63 }
64
65 }
66 }// end if(WSAEWOULDBLOCK==ret)
67 else
68 {
69 /*!<网络出现其他错误*/
70 closesocket(m_clientSocket);
71 return -6;
72 }
73 }
74 else
75 {
76 return 0;
77 }
78 }
参考:
Window+TCP+connect 超时阻塞解决办法 - 鹰之翔 - 博客园 (cnblogs.com)
http://olive101.blog.163.com/blog/static/2051263201011221915696/
http://blog.csdn.net/saspss/article/details/8487678
http://blog.csdn.net/u014805066/article/details/50592415

