阻塞套接字和非阻塞套接字的奇怪有关问题,大侠进

阻塞套接字和非阻塞套接字的奇怪问题,大侠进。
connect之后调用recv,
在阻塞下recv到的数据是正常的,
而非阻塞下recv返回始终是-1 errno == EAGAIN, 即使用while 1 recv,返回值始终是 -1 errno == EAGAIN

代码如下
阻塞的connect代码就不贴了,
非阻塞的connect如下

static int _connect(struct sockaddr_in *sockad, int *sockid)
{
int sock;
int reuse = 1;
int iRet;

fd_set rdevents,wrevents,exevents;
struct   timeval tv;
// struct   timeval nTimeout;
socklen_t sLen;
int iSocket = 0;

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock < 0)
{
return -1;
}

if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int)) < 0)
{
close(sock);
return -1;
}

//设置为非阻塞模式
unsigned long ul = 1;
ioctl(sock, FIONBIO, &ul);

//与服务器端建立连接
if(((iRet = connect(sock, (struct sockaddr *)sockad, sizeof(struct sockaddr_in))) < 0) && errno != EINPROGRESS)
{
//失败
close(sock);
iRet = -1;
goto leave;
}


//若没有直接连接成功则需要等待
if(0 != iRet)
{  
//把先前的套接字加到读集合里面
FD_ZERO(&rdevents);
FD_SET(sock, &rdevents);  
wrevents = rdevents;  
//异常集合
exevents = rdevents;   
//设置时间为5秒
tv.tv_sec = 5;  
tv.tv_usec = 0;

iRet = select(sock + 1, &rdevents, &wrevents, &exevents, &tv);
if (iRet < 0) 
{  
     //错误处理
    close(sock);
    sock = INVALID_SOCKET;
    iRet = td_failure;
goto leave;
}
else if(0 == iRet) 
{  
     //超时处理
    close(sock);
    sock = INVALID_SOCKET;
    iRet = td_failure;
goto leave;
}
else 
{
if(2 == iRet) 
{  
int error;
int len = sizeof(error); 
getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, (socklen_t*)&len); 
if (error) 

//超时处理
    close(sock);
    sock = INVALID_SOCKET;
iRet = td_failure;
goto leave;

}

     if(!FD_ISSET(sock, &rdevents) && !FD_ISSET(sock, &wrevents)) 
{
       close(sock);
      sock = INVALID_SOCKET;
iRet = td_failure;
goto leave;
     }

     if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &iRet, &sLen)<0)
    {
//perror("getsockopt ");
    }
   
    if(2 == iRet)
    {
close(sock);
    sock = INVALID_SOCKET;
iRet = td_failure;
goto leave;
    }
}
}
leave:
*sockid = sock;
return iRet;
}

------解决方案--------------------
在非阻塞模式下 返回EAGAIN是正常情况的!没有可读数据而已!继续recv就好!