select函数用法详解

1. select函数

select的作用:

轮询的方式,从多个文件描述符中获取状态变化后的情况。

头文件

#include <sys/time.h>   //for struct timeval
#include <unistd.h>     //for select

函数原型

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

参数解释

  • nfds: 要检测的文件描述符的范围,为文件最大描述符+1
  • readfds: 包含所有可能因状态变成可读而触发select函数返回的文件描述符
  • writefds: 包含所有可能因状态变成可写而触发select函数返回的文件描述符
  • exceptfds: 包含所有可能因状态发生异常而触发select函数返回的文件描述符
void FD_CLR(int fd, fd_set *set);       //将fd在set中去除
void FD_SET(int fd, fd_set *set);       //将fd添加到set中
int  FD_ISSET(int fd, fd_set *set);     //检查set中fd是否有状态变化
void FD_ZERO(fd_set *set);              //清空整个set
  • timeout:
struct timeval {
     long    tv_sec;         /* seconds */
     long    tv_usec;        /* microseconds */
};

返回值
当超时或其中一个/多个文件描述符发生变化时,此函数将返回,返回值:

  • -1: 函数执行出错
  • 0: 超时,并将时间结构体清空为0
  • 0: 状态变化的文件描述符的个数

基本实例

fd_set rdfds;   
struct timeval tv;
int rtn = 0;

FD_ZERO(&rdfds);     //清空fd_set
FD_SET(socket, &rdfds);  //将要检测的socket描述符加入到fd_set集合中

tv.tv_sec = 2;
tv.tv_usec = 1000;      //设置超时时间为2s+1ms

rtn = select(socket+1, &rdfds, NULL, NULL, &tv);

if(rtn < 0)
    perror("select");
else if(0 == rtn)
    printf("timeout\n");
else
{
    printf("rtn = %d\n", rtn);      //查看有多少个文件描述符发生了变化
    
    if(FD_ISSET(socket, &rdfds))    //判断下这个socket是否状态真的变成了可读
    {
        recv(...);
    }
}

2. select做时间函数

void time_delay(int seconds)
{ 
    struct timeval tv;
    int err;
    
    tv.tv_sec = seconds;     //超时时间
    tv.tv_usec = 0;
    
    do
    {
       err = select(0,NULL,NULL,NULL,&tv);  //将nfds设置为0即为超时函数
    }while(err<0 && errno==EINTR);          //
}

3. 未完待续

posted @ 2018-04-10 20:25  Jimmy_Nie  阅读(4499)  评论(0编辑  收藏  举报