现象:一般情况下,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 }
参考:
http://olive101.blog.163.com/blog/static/2051263201011221915696/
http://blog.csdn.net/saspss/article/details/8487678
http://blog.csdn.net/u014805066/article/details/50592415