Linux——select()浅谈


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);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值