Darwin中socket接收前使用select等待

​编者:李国帅​


背景原因:

因为darwin rtsp项目中所有的socket都是用了非阻塞模式,所以发送和接收不需要使用select,直接调用send和recv即可。

但是如果无数据,会发现出现近乎死循环的行为。

 

OS_Error Socket::Read(void *buffer, const UInt32 length, UInt32 *outRecvLenP)

OS_Error UDPSocket::RecvFrom(uSockAddr& outRemoteAddr,void* ioBuffer, UInt32 inBufLen, UInt32* outRecvLen)

看来还必须在recv或者recvfrom出现阻塞之前,使用select等待一下,但是等待的时间必须要小。

 

所需资源:

Vc socket

 

接收前的等待:

 

//iMode = 1;//设置非阻塞方式连接
//iMode= 0 ; //可以根据实际情况考虑 再设回阻塞模式
int err =::ioctlsocket(fFileDesc, FIONBIO,&iMode);

int ret = 0;
fd_set fdRecv;
FD_ZERO(&fdRecv);
FD_SET(fFileDesc,&fdRecv);//don't forget to error check the connect()!

struct timeval toRecv ; //select 模型,即设置超时
toRecv.tv_sec = 0;
toRecv.tv_usec = 1000;//1毫秒;
ret = select(0,&fdRecv, 0, 0,&toRecv);
FD_CLR(fFileDesc,& fdRecv);

if(ret == SOCKET_ERROR)//失败
{
*outRecvLen = 0;
nlasterr = OSThread::GetErrno();

if(nlasterr != EINPROGRESS && nlasterr != EINTR)
{
if((this->IsConnected()))
{
CNetLog::printlog(_T("%s ~kConnected for ::select error. GetErrno=%d\n"),__FUNCTIONT__,nlasterr);
fState ^= kConnected;//turn off connected state flag
}
return(OS_Error)nlasterr;
}
else
{
return OS_NoErr;//socket并没有出错,可以继续。
}
}
elseif(ret == 0)
{
//CNetLog::printlog(_T("%s select timeout\n"),__FUNCTIONT__);
*outRecvLen = 0;
nlasterr =(OS_Error)EINPROGRESS;//超时

return nlasterr;
}