Windows下使用CSoket连接未知的服务端IP或未开启的服务端问题

问题由来:使用CSoket连接未知的服务端IP或未开启的服务端时,直接调用BOOL bRet =CSocket::Connect(strServerIP, nPort)发生长时间的阻塞,导致程序退出时存在进程残留的问题。

问题原因

BOOL CSocket::ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
	if (m_pbBlocking != NULL)
	{
		WSASetLastError(WSAEINPROGRESS);
		return  FALSE;
	}

	m_nConnectError = -1;

	if (!CAsyncSocket::ConnectHelper(lpSockAddr, nSockAddrLen))
	{
		if (GetLastError() == WSAEWOULDBLOCK)
		{
			while (PumpMessages(FD_CONNECT))
			{
				if (m_nConnectError != -1)
				{
					WSASetLastError(m_nConnectError);
					return (m_nConnectError == 0);
				}
			}
		}
		return FALSE;
	}
	return TRUE;
}

CSocket::Connect()内部调用CSocket::ConnectHelper()

发送链接请求(瞬间执行完毕),之后在线程队列中轮询抓取FD_CONNECT消息,在此阻塞。

解决方法:直接调用ConnectHelper发送链接请求,然后通过select设定自定义时间,根据返回值确认是否真正链接。参考此处5楼

可以使用CAsyncSocket类中的OnConnect(int nErrorCode)函数
如果是超时的话,回返WSAETIMEDOUT (值为10060),可通过对nErrorCode进行判断来做出对用户提示超时信息。
但是此方法的返回时间无法设置,大概在20秒左右。
还可以通过一下步骤:
1,设置为非阻塞套接字 ;
2,connect, ;
3,select判断超时。
由于CAsyncSocket本身即为非阻塞套接字,所以只需在正常的connect语句后面添加select的判断语句来确定是否超时。

CAsyncSocket  sock;
struct   timeval   tmo   ;  
fd_set   r;  
FD_ZERO(&r);  
FD_SET(sock.m_hSocket,   &r);  
tmo.tv_sec   =   3;   //连接超时3秒  
tmo.tv_usec  =   0;  
ret  =  select(0, 0, &r, 0, &tmo);

通过参考MSDN的select函数的返回值的说明:The select function returns the total number of socket handles that are ready and contained in the FD_SET structures, zero if the time limit expired, or SOCKET_ERROR if an error occurred.
可知,当ret==0时超时。
此外还有一种方法:
int TimeOut=6000; //设置发送超时6秒

 if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char   *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
 {  
  return   0;  
 }  
 TimeOut=6000;//设置接收超时6秒  
 if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char   *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
 {  
  return   0;  
 }   

使用setsockopt函数需要使用socket2
问题是我用的是socket2 但是没有成功实现这种方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值