您的位置:首页 > 运维架构 > Linux

Linux——select()浅谈

2015-08-07 14:25 841 查看

select()确定一个或多个套接口的状态,本函数用于确定一个或多个套接口的状态,对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。

程序会停在select这里等待,直到被监视的套接口有一个或多个发生了状态改变。
select函数原型如下:

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

函数的最后一个参数timeout是超时时间。即,select()最多等待时间,对阻塞操作则为NULL。其结构如下:

struct timeval
{
long tv_sec; //seconds
long tv_usec; //microseconds
};

readfds、writefds、exceptfds三个参数是一样的类型,而fd_set结构用来表示一组等待检查的套接口,在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足条件的套接口的数目。

这三个参数都是一个套接口的集合:

readfds:(可选)指针,指向一组等待可读性检查的套接口。

writefds:(可选)指针,指向一组等待可写性检查的套接口。

exceptfds:(可选)指针,指向一组等待错误检查的套接口。

如果对readfds、writefds或exceptfds中任一个组类不感兴趣,可将它置为空NULL。

在winsock.h头文件中共定义了四个宏来操作描述字集:

1、FD_CLR(s,*set):从集合set中删除描述字s。

2、FD_ISSET(s,*set):若s为集合中一员,非零;否则为零。

3、FD_SET(s,*set):向集合添加描述字s。

4、FD_ZERO(*set):将set初始化为空集NULL。

另外,FD_SETSIZE变量用于确定一个集合中最多有多少描述字(FD_SETSIZE缺省值为64,可在包含winsock.h前用#define FD_SETSIZE来改变该值)。对于内部表示,fd_set被表示成一个套接口的队列,最后一个有效元素的后续元素为INVAL_SOCKET。

如果我们程序里只想检测某个socket是否有数据可读,我们可以这样:

fd_set rdfds;
struct timeval tv;
int ret;

FD_ZERO(&rdfds);
FD_SET(socket, &rdfds);

tv.tv_sec = 1;
tv.tv_uses = 500;

ret = select(socket+1, &rdfds, NULL, NULL, &tv);
if(ret < 0)
{
perror(“select”);
}
else if(ret = = 0)
{
printf(“time out”);
}
else
{
printf(“ret = %d/n”,ret);
if(FD_ISSET(socket, &rdfds))
{
/* 读取socket句柄里的数据 */
recv( );
}
}


注意select函数的第一个参数,是所有加入集合的句柄值的最大那个那个值还要加1.比如我们创建了3个句柄:

int sa, sb, sc;

sa = socket(……);
connect (sa,….);

sb = socket(….);
connect (sb,…);

sc = socket(….);
connect(sc,…);

FD_SET(sa, &rdfds);
FD_SET(sb, &rdfds);
FD_SET(sc, &rdfds);


在使用select函数之前,一定要找到3个句柄中的最大值,我们一般定义一个变量来保存最大值,取得最大socket值如下:

int maxfd = 0;

if(sa > maxfd) maxfd = sa;
if(sb > maxfd) maxfd = sb;
if(sc > maxfd) maxfd = sc;


然后调用select函数:

ret = select (maxfd+1, &rdfds, NULL, NULL,&tv);

同样的道理,如果我们是检测用户是否按了键盘进行输入,我们就应该把标准输入0这个句柄放到select里来检测,如下:

FD_ZERO(&rdfds);
FD_SET(0, &rdfds);

tv.tv_sec = 1;
tv.tv_usec = 0;

ret = select (0+1, &rdfds, NULL, NULL, &tv);
if(ret < 0)
{
perror(“select”);
}
else if(ret = = 0)
{
printf (“time out/n”);
}
else
{
scanf(“%s”,buf);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息