例如recv()等了一个小时还没有收到数据,怎么跳出

解决方案 »

  1.   

    1. 用setsockopt函数设置超时。2. 或用WM_TIMER设置定时器,到时间了就调用WSACancelBlockingCall取消阻塞调用,
    这样recv就会返回,返回值是一个特别的值,这个查查Msdn就知道了。3. 用select语句对socket句柄进行数据检查。这是unix socket编程的经典方法,windows也支持。
      

  2.   

    setsockopt()怎么设置,在什么时候设置,可否给个例子
      

  3.   

    int TimeOut=6000;  //收发超时3秒 
    if(!SetSockOpt(SO_SNDTIMEO,(char *)&TimeOut,
    sizeof(TimeOut)))
    {
    return FALSE;
    }
      

  4.   

    To:farfh(慕容长风) 
    我开了一个收数据的线程,要设置recv()超时,SetSockOpt()要放在何处呢
      

  5.   

    timeval read_timeout ;  
        fd_set  read_fd;      read_timeout.tv_sec = 5;
        read_timeout.tv_usec = 0;    FD_ZERO(&read_fd);
        FD_SET(m_hWriterSocket,&read_fd);    nErr = ::select(0,&read_fd,0,0,&read_timeout);
        if (nErr ==0)
         {
             //MessageBox();
    goto ConnectBreak;
         }
        if( nErr == SOCKET_ERROR )
        {
          //MessageBox();
          goto ConnectBreak;
         }        
         nErr = ::recv(m_hWriterSocket,
                       getbuf(),
                       LengthNeedRead,
                       0);  
         if (nErr ==0)
         {
            //MessageBox();
    goto ConnectBreak;
          }
          else{
               if( nErr == SOCKET_ERROR )
                {
                  //MessageBox();
                  goto ConnectBreak;
       }
                else{
                   //do you process 
                 }
    }
      

  6.   

    int Timeout=60000
    connect_flag_cmd= connect(cmdsock,(struct sockaddr FAR *)&from,sizeof(from));
    status=setsockopt(cmdsock,IPPROTO_TCP, SO_RCVTIMEO, (char *)&Timeout, sizeof(Timeout));status=-1,setsockopt失败,为什么
      

  7.   

    好象是WinSock不支持SO_RCVTIMEO.试试用:
    /*
    返回:
    >0: 接收长度
    other: failed
    */
    int sockRecvBuf(int sock,char *pszBuf,int iMaxLen,int rcvTmOut)
    {
    int retval;
    struct timeval timeVal; 
    fd_set setId; if(rcvTmOut>0)
    {
    timeVal.tv_sec=rcvTmOut;
    timeVal.tv_usec=0; FD_ZERO(&setId);
    FD_SET((unsigned)sock,&setId); retval=select(0,&setId,NULL,NULL,&timeVal);
    if(retval==SOCKET_ERROR)return -1;
    if(retval==0)return 0; //time out
    //if(!FD_ISSET(sock,&setId))return 0;
    } retval=recv(sock,pszBuf,iMaxLen,0);
    if(retval<0)
    {
    strcpy(gszErrMsg,"receive error");
    return -2;
    } return(retval);
    }
      

  8.   

    用select太费了,如果是我的话我宁愿则EVENT,异步收发,这样也较简单。
    给个MFC下完整代码,使用API的道理是一样的。一般说来是没问题的,总之要先setsockopt,才能connect,详见msdn。
    CCFSocket sk;
    if(!sk.Create())
    {
    MsgBox("连接时候出现错误,请尝试从新连接");
    sk.Close();
    return FALSE;
    }
    if(!sk.AsyncSelect(0))
    {
    return FALSE;

    }
    DWORD ld=0;
    if(!sk.IOCtl(FIONBIO   ,&ld))
    {
    return FALSE;
    }
    int TimeOut=6000;  //收发超时6秒 
    if(!sk.SetSockOpt(SO_SNDTIMEO,(char *)&TimeOut,
    sizeof(TimeOut)))
    {
    return FALSE;
    }
    if(!sk.SetSockOpt(SO_RCVTIMEO,(char *)&TimeOut,
    sizeof(TimeOut)))
    {
    return FALSE;
    }

    return TRUE;
    if(!sk.Connect(m_Ip,SERVER_PORT))
    {
    sk.Close();
    return FALSE;
    }
      

  9.   

    附带说一句,在WINDOWS下编程,所有错误都可以使用WSAGetLastError()或者GetLastError()查出错误来,如果设置没有成功,请检查错误代码。
      

  10.   

    是不是每次调用recv()之前都要调用一次select()?
    select()会不会象WSAAsyncSelect()一样把socket变成非堵塞
      

  11.   

    int Timeout=6000;
    connect_flag_cmd= connect(cmdsock,(struct sockaddr FAR *)&from,sizeof(from));

    timeVal.tv_sec=Timeout;
    timeVal.tv_usec=0;
    FD_ZERO(&setId);
    FD_SET((unsigned)cmdsock,&setId);
    retval=select(0,&setId,NULL,NULL,&timeVal);
    按F5,运行到select()就堵住了,为什么