struct timeval timeout={3,0};
FD_ZERO(&fdset); //每次循环都要清空集合,否则不能检测描述符变化;
FD_SET(sk,&fdset); //添加描述符;
int ret = select(0, &fdset, NULL, NULL, &timeout);
if(ret<=0)
return FALSE;
else if(FD_ISSET(sk,&fdset))
{
return TRUE;
}
return FALSE;
比如你有1 2 3三个fd,你用select来判断可读可写状态,select返回之后,要么出错,要么超时,要么得到了某些fd的可读可写状态。
假如只有1可读,那么2和3已经从fd_set里面去掉了,然后你开始对1 2 3这三个fd以次调用FD_ISSET,如果返回真,说明对应的fd可读。
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);返回时告诉我们哪些描述符已经准备好了,是读,写,还是异常
至于FD_ISSET,则是检测哪一个描述符准备好了,描述符集中可能会有很多描述符,而不只是一个。
当多个socket检测时
fd_set waitres;
FD_ZERO(&waitres);
//四个socket存放在容器内,用select选择是哪个socket收到了数据;
FD_SET(pCHCVideoDevice->recvhdsock, &waitres);
FD_SET(pCHCVideoDevice->recvdatasock, &waitres);
FD_SET(pCHCVideoDevice->stopsock, &waitres);
FD_SET(pCHCVideoDevice->keeplivesock, &waitres);
//进行循环
while (circle)
{
timeval tmptimer;
tmptimer.tv_sec = 3 ; <pre name="code" class="cpp"> <span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">tmptimer.tv_usec = 0;</span>
//对waitres做备份tmpres,操作tmpres; fd_set tmpres = waitres;
<pre name="code" class="cpp" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 24px;"> int res = select(0, &tmpres, 0, 0, &tmptimer);
if (res == 0)
{
}
if (res == SOCKET_ERROR)
{
res = WSAGetLastError();
goto recv_quit;
}
//如果是心跳socket接收到包;
if (FD_ISSET(pCHCVideoDevice->keeplivesock, &tmpres))
{
int recvres = recvfrom(pCHCVideoDevice->keeplivesock, buf, 1500, 0, (struct sockaddr *)&rcvaddr, &addr_len);
}
//如果是请求停止视频流的包;
if (FD_ISSET(pCHCVideoDevice->stopsock, &tmpres))
{
。。。。。。