c语言select函数头文件,简述select函数的功能与调用方法

使用select

首先我们需要解答一些疑惑。为什么要使用select函数?

比如你有一个服务器程序,维护着N多个TCP连接,你如何去判断这些TCP连接上有数据传送过来了呢?最傻瓜的办法就是隔一定时间去循环读一次所有TCP连接对应的

再比如你想编写一个非

如此等等,简而言之,如果你需要监听一组文件描述符(

简单了解了select的功能以后,那么到底怎样调用select函数呢?

1、依赖

select函数是在系统库”sys/select.h”中声明的,其实在系统库“types.h”也include了一下“sys/select.h”,所以,我们在调用select函数之前务必加上头文件”sys/select.h”或者“types.h”。

2、依赖结构体“struct timeval”和“fd_set”

select有五个参数,三种类型,分别是int、struct timeval *和fd_set*,fd_set在”sys/select.h”定义,struct timeval在“time.h”中定义,所以也别忘了把头文件“time.h”加上。

3、需要配合宏变量FD_ZERO(fdsetp)、FD_SET(fd, fdsetp)、FD_ISSET(fd, fdsetp)和FD_CLR(fd, fdsetp)一起调用

其实这四个宏变量的调用方式类似于我们的普通函数,功能也很类似。看看下面的两个宏变量,你应该就理解了吧。

#define min(a,b) ((a) < (b) ? (a) : (b))

#define max(a,b) ((a) > (b) ? (a) : (b))

(1)宏变量FD_ZERO(fdsetp)用来清空整个fd_set结构体对象,形象地说就是fd_set结构体对象用来存储一组你关心的文件描述符(套接字),FD_ZERO负责清空该对象中已有的文件描述符(套接字)。注意:fdsetp需要传入fd_set结构体对象的指针。

(2)宏变量FD_SET(fd, fdsetp)用来将你关心的文件描述符(套接字)fd存入fd_set结构体对象fdsetp中去。注意:fdsetp需要传入fd_set结构体对象的指针。

(3)宏变量FD_ISSET(fd, fdsetp)用来判断你指定的文件描述符(套接字)fd是否满足可读、可写或者错误条件,如果满足则返回非0值,否则返回0。注意:fdsetp需要传入fd_set结构体对象的指针。

(4)宏变量FD_CLR(fd, fdsetp)用来将你指定的文件描述符(套接字)fd从指定fd_set对象fdsetp中清除,即表示不再关心此fd。注意:fdsetp需要传入fd_set结构体对象的指针。

通常情况下,你关心文件描述符(套接字)的几种状态就定义几个fe_set对象,比如我既关心可读属性又关心可写属性,还关心错误属性,那么我就需要分别定义如下三个fd_set对象。

fd_set readfds;

fd_set writefds;

fd_set errorfds;

由此看来,你关心几种状态,也得相对应的调用几次上面四个宏变量。

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

第一个参数:nfds是你关心的所有文件描述符中最大者的值加一;第二、三、四个参数:分别传入可读、可写和错误集合fd_set对象的指针&readfds、&writefds和&errorfds,如果不关心某种状态,就将某种状态对应的参数传入NULL值即可;第五个参数:timeout传入select的阻塞时间,如果传入NULL则select函数会一直阻塞直到有文件描述符可读、可写或者错误。

最后,给出一个整体的调用实例如下。

#include

#include

#include

#define SLEEP_TIME 10

#define MAX_SESSION_UP 100

int main(void)

{

int i;

int fd_num;

int accept_fd_up[MAX_SESSION_UP] = {0};

fd_set readfds;

struct timeval select_timeval;

//you can add some task here, so the fd in accept_fd_up maybe changed here

while (1)

{

FD_ZERO(&readfds);

for (i=0; i

{

if (accept_fd_up[i] > max_sock)

max_sock = accept_fd_up[i];

if (accept_fd_up[i] > 0)

FD_SET(accept_fd_up[i], &readfds);

}

fd_num = select(max_sock+1, &readfds, NULL, NULL, &select_timeval);

if (fd_num < 0)

{

perror("select");

continue;

}

else if (0 == fd_num)

{

printf("select timeout...\n");

//resert the select_time after timeout

select_timeval.tv_sec = SLEEP_TIME;

select_timeval.tv_usec = 0;

//you can add some task here, so the task could work a time every SLEEP_TIME

//the fd in accept_fd_up maybe changed here

continue;

}

for (i=0; i

{

if (FD_ISSET(accept_fd_up[i], &readfds))

{

printf("do case in do_fd_up: %d,%d", accept_fd_up[i], i);

//you can add some task here to deal with the change of the fd

//the fd in accept_fd_up also maybe changed here

}

}

}

}

该实例仅仅只是一个框架而已,它假设有一组大小为MAX_SESSION_UP的int类型数组存储了一堆文件描述符,其中凡是大于0的则默认为我们关心的文件描述符,需要select监管它,小于等于0的则被忽视。

除非注明,文章均为CppLive 编程在线原创,转载请注明出处,谢谢。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值