写了个网络程序,在MFC做的,用了CSocket,都做完了,才发现如果在连接的IP不存在的情况下,需要等待20秒左右才会返回连接错误。在不改成CAsyncSocket的情况下,能设置连接超时吗?在网上搜了无数种方法来设置连接超时,都不管用,仍然是要等20秒。
即便是我用了个Timer来返回,也是要等到20秒之后才执行。
比如,我用一个变量 int a = 0;如果连接成功时令a=1。用Timer过3秒检测a的值。我是先SetTimer,然后再Connect的。
但是我发现,SetTimer中的事件是要等到Connect返回了值之后才开始执行的。也就是如果连接的IP不存在,仍然要先等20秒。
谁能指点一下吗?先谢谢了。

解决方案 »

  1.   

    int setsockopt(
      SOCKET s,
      int level,
      int optname,
      const char* optval,
      int optlen
    );SO_RCVTIMEO int Receives time-out in milliseconds (available in the Microsoft implementation of Windows Sockets 2).
    SO_SNDTIMEO int Sends time-out in milliseconds (available in the Microsoft implementation of Windows Sockets 2).  
      

  2.   

    BOOL SetTimeOut(SOCKET s, int nTime, BOOL bRecv)
    {
     return setsockopt(s, SOL_SOCKET, bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
    }
      

  3.   

    Sorry
    return setsockopt(s, SOL_SOCKET, bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
    -->
    return SOCKET_ERROR != setsockopt(s, SOL_SOCKET, bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
      

  4.   

    在建立好socket之后,调用connect之前,先设置socket为非阻塞模式。
    还是给你个例子吧int TCP_Connect(const char *serverIP, int port, int iTimeOut)
    {
    struct timeval tv; 
    int error;
    fd_set writefds; 
    struct sockaddr_in servaddr;
    int ret;
    u_long ul = 1;//设置非阻塞方式连接
    BOOL bNodelay = TRUE; //1.socket
    int fd = socket(PF_INET,SOCK_STREAM, 0);
    if(fd <=0 )
    {
    LogError("create socket failed.%s", strerror(errno));
    fd = 0;
    return -1;
    } //2.fcntl
    #ifdef LINUX_PLATFORM fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);#else
    if(ioctlsocket(fd, FIONBIO, (unsigned long*)&ul) != 0)
    {
    LogError("ioctlsocket socket failed:%ld", GetLastError());
    }
    #endif
    //3.connect
    //bzero(&servaddr, sizeof(servaddr));
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    #ifdef LINUX_PLATFORM
    inet_aton((const char*)serverIP, &servaddr.sin_addr);
    #else
    servaddr.sin_addr.S_un.S_addr = inet_addr(serverIP);
    #endif
    servaddr.sin_port = htons(port);
      if(iTimeOut <= 0)
      {
       iTimeOut = 5;
      }
      
    if(connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) <  0) 
    { //if(connect failed)
    #ifdef LINUX_PLATFORM
    if (errno == EINPROGRESS)
    #else
    ret = GetLastError();
    if(ret == WSAEINPROGRESS || ret == WSAEWOULDBLOCK)
    #endif
    {// if it is in the connect process 
    while(1)
    {
    tv.tv_sec = iTimeOut; 
    tv.tv_usec = 0; 
    FD_ZERO(&writefds); 
    FD_SET((u_long)fd, &writefds); 
    if( select(fd + 1, NULL, &writefds, NULL, &tv) > 0 )

    int len = sizeof(int); 
    //skip the firewall setting.
    getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len); 
    if(error == 0) 
    ret = 0; 
    else 
    ret = -1; 
    break;
    }
    else   
    {
    #ifdef LINUX_PLATEFORM
    if(errno == EINTR || errno == EAGAIN )
    continue;
    #endif LogError("connect time out.");

    ret = -1;//timeout or error happen 
    break;//
    }
    }
    }//end if it is in the connect process 
    else 
    {
    ret = -1; 
    }
    }//end if(connect failed) 
    else   ret = 0;  if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&bNodelay, sizeof(bNodelay) ) != 0)
    {
    LogError("setsockopt socket failed.%s", strerror(errno));
    return -3;
    }

    if(ret < 0)
    {
    #ifdef LINUX_PLATFORM
    close(fd);
    #else
    closesocket(fd);
    #endif
    fd = 0;
    LogError("connect %s failed, errno:%d.", serverIP, errno);
    return ret;
    } return fd;
    }
      

  5.   

    嗯,需要了解 Socket的阻塞和非阻塞模式...
      

  6.   

    再问一个很弱的问题,怎么从CSocket* 转化为SOCKET
      

  7.   

    setsockopt 似乎没用吧,我在网上看说setsockopt不支持SO_RCVTIMEO类型
      

  8.   

    CSocket* 转化为SOCKET有何用?强制转换
      

  9.   


    SOCKET保存了套接字信息,可以用Detach()的方法提取SOCKET,下次使用时可以用Attach()方法
    SOCKET g_socket;
    ///
    CSocket m_clientSocket;
    ///
    g_socket = m_clientSocket.Detach();
    ///其它线程
    CSocket socket;
    socket.Attach(g_socket);
    ////