流程一:
int iSck = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8000);
saddr.sin_addr.s_addr = inet_addr("192.168.1.233");int ret = 0;
unsigned long ulNoBlock = 1;
ret = ioctlsocket(iSck, FIONBIO, (unsigned long*)&ulNoBlock);
if(ret==SOCKET_ERROR)
return;int iError = WSAGetLastError();
ret = connect(iSck, (LPSOCKADDR)&saddr, sizeof(saddr));
iError = WSAGetLastError();struct timeval timeout ;
fd_set r;
FD_ZERO(&r);
FD_SET(iSck, &r);
timeout.tv_sec = 10;  
timeout.tv_usec =0;
int max = 1;if (ret<0)
{
  if (iError==WSAEWOULDBLOCK)
  {
    ret = select( max+1, 0, &r, 0, &timeout);
    if ( ret <= 0 )
    {
      iError = WSAGetLastError();
      ::closesocket(iSck); 
      return;
    }
    else
    {
      ... //说明连接成功,可以send recv数据了
    }
  }
  else
  {
    //连接有异常,关闭socket
    ::closesocket(iSck); 
    return;
  }
}
else
{
  ... //说明连接成功,可以send recv数据了
}
...流程二:
  int iSck = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in saddr;
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(8000);
  saddr.sin_addr.s_addr = inet_addr("192.168.1.233");  int iError = WSAGetLastError();
  ret = connect(iSck, (LPSOCKADDR)&saddr, sizeof(saddr));
  if (ret<0)
  {
    iError = WSAGetLastError();
    ::closesocket(iSck); 
    return;
  }
  ... //说明连接成功,可以send recv数据了
做这个实验,假设目标主机8000端口未打开当连接内网主机192.168.1.233时
  流程一很慢,一定要等到设置的超时10s到,并且我不知道如何得到失败原因,表现很差,我不喜欢;
  流程二很迅速,并能getlasterror能得到错误码是10061,意思是对方拒绝,表现很好,我喜欢;当连接外网主机202.168.1.233时,当然该主机是不存在的
  流程一一定要等到设置的超时10s到,这个时间是可以控制的,并且我不知道如何得到失败原因,表现比流程二稍强,我喜欢;
  流程二很慢,大约要20秒,能getlasterror能得到错误码是10060,意思是连接timeout,表现不太好,我不喜欢;大家觉得我的理解(包话注释)对不对,请指教;

解决方案 »

  1.   

    当连接内网主机192.168.1.233时
      流程一很慢,一定要等到设置的超时10s到,并且我不知道如何得到失败原因,表现很差,我不喜欢;
      流程二很迅速,并能getlasterror能得到错误码是10061,意思是对方拒绝,表现很好,我喜欢;
    ----------------
    楼主的意思是端口不可达,select也可以做到迅速判断,select( max+1, &r, &w, 0, &timeout);
    应该同时检测第二个参数fd_set* readfds,这样select立即返回,继而recv会得到RESET报文的的错误,判定连接失败
    一般来说,要控制connect时间,都用select模型
      

  2.   

    对,就是wocow3解释的这样,但是select( max+1, &r, &w, 0, &timeout)还是不能迅速判判断[rst,ack],select( max+1, &r, &w, &e, &timeout)才可以,后面这贴子也描述了同样的意思
    http://hi.baidu.com/zxhouse/blog/item/9e89fd644e768ff6f73654c0.html不过看到这贴子上也有人评论说用第二个参数r即可,不必用e,为何我的还不行,另本人是winxp平台;
      

  3.   

    我并没有实测select( max+1, &r, &w, 0, &timeout)不检查错误的方式,因为这里是远端主机端口不可达,本地会明确的收到远端的RESET包,理论上select( max+1, &r, &w, 0, &timeout)也可以做到立即返回,但还是已实测为主