分享

linux—select详解

 徐子钦 2009-12-20
boboiask的专栏
一步一步向前走
登录 注册 欢迎 退出 我的博客 配置 写文章 文章管理 博客首页   全站 当前博客  空间 博客 好友 相册 留言 用户操作
[留言]  [发消息]  [加为好友] 
ID:boboiask
共2494次访问,排名2万外,好友0人,关注者1人。
的文章
原创 12 篇
翻译 0 篇
转载 6 篇
评论 0 篇
订阅我的博客
    
 
 
 
[编辑]boboiask的公告
[编辑]文章分类
存档
2009年07月(5)
2009年06月(2)
2009年04月(10)
2009年03月(1)
  linux—select详解 收藏
linux—select详解
 
select系统调用时用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变。
关于文件句柄,其实就是一个整数,通过socket函数的声明就明白了:
int socket(int domain, int type, int protocol);
我们最熟悉的句柄是0、1、2三个,0是标准输入,1是标准输出,2是标准错误输出。0、1、2是整数表示的,对应的FILE *结构的表示就是stdin、stdout、stderr。

继续上面的select,就是用来监视某个或某些句柄的状态变化的。select函数原型如下:
int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
函数的最后一个参数timeout是一个超时时间值。其类型是struct timeval *,即一个struct timeval结构的变量的指针,所以我们在程序里要声明一个struct timeval tv;然后把变量tv的地址&tv传递给select函数。struct timeval结构如下:
struct timeval
{
       long tv_sec;  //seconds
       long tv_usec; //microseconds
};
第2、3、4三个参数是一样的类型;fd_set *,即我们在程序里要申请几个fd_set类型的变量,比如rdfds,wtfds,exfds,然后把这个变量的地址&rdfds,&wtfds,&exfds传递给select函数。这三个参数都是一个句柄的集合,第一个rdfds是用来保存这样的句柄的:当句柄的状态变成可读时系统就告诉select函数返回,同理第二个函数是指向有句柄状态变成可写时系统就会告诉select函数返回,同理第三个参数exfds是特殊情况,即句柄上有特殊情况发生时系统会告诉select函数返回。特殊情况比如对方通过一个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 (1, &rdfds,NULL,NULL,&tv);
if(ret < 0) perror(“select”);
else if (ret = = 0) printf (“time out\n”);
else{
       scanf(“%s”,buf);
}
发表于 @ 2009年04月07日 22:58:00 | 评论( loading... ) | 编辑| 举报| 收藏
旧一篇:内存中堆和栈 | 新一篇: HP大中华区总裁孙振耀退休感言
相关文章
UNIX C的一篇文章UNIX C的一篇文章 [转]Linux网络编程一步一步学-select详解Linux网络编程一步一步学-select详解Linux select()详解(转载)epoll使用详解(精髓)linux网络编程linux下网络传输测速程序给boboiask的留言只有注册用户才能发表评论!登录注册姓   名:
校验码:
Copyright © boboiask
Powered by CSDN Blog  
 热评博文榜【博客首页】【作家协会】2009年度编程语言之争 涨幅第一:C#
靳雄飞:耐住寂寞,享受成功
火!《拯救程序员》连载公告
李开复:不是每个人都适合创业
根治色情网站,进行产业调整是根本之路
高峰:又进到Google偷偷写了些东西
BT结束,高宽带有何用?
袁萌:Linux前方的一团迷雾

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/boboiask/archive/2009/04/07/4055655.aspx

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多