UNIX网络编程套接字 -- select

select函数允许进程指示内核等待多个事件中的任何一个发生,并且在有一个或多个事件发生或经历一段指定时间后才唤醒。

 

1.函数原型:

int select (int maxfd + 1,fd_set *readset,fd_set *writeset, fd_set *exceptset,const struct timeval * timeout);

参数:

maxfd + 1: 表示待测试的描述符个数。加1的作用是指,描述符计数从0开始,则用加1表示个数。

 

readset,writeset,exceptset:

让内核测试读,写,异常条件的描述符。如果我们对某一个条件不感兴趣,则用NULL表示。

这三个参数是 值-结果 参数,函数返回时,结果将指示哪些描述符已就绪。在每次调用 select时,需要将所有描述符集内所关心的位均置1.

struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor),即文件句柄。fd_set集合可以通过一些宏由人为来操作。

FD_ZERO(fd_set *fdset):清空fdset与所有文件句柄的联系。 
FD_SET(int fd, fd_set *fdset):建立文件句柄fd与fdset的联系。 
FD_CLR(int fd, fd_set *fdset):清除文件句柄fd与fdset的联系。 
FD_ISSET(int fd, fdset *fdset):检查fdset联系的文件句柄fd是否可读写,>0表示可读写。 
 

(1)执行FD_ZERO(&set); 则set用位表示是0000,0000。

(2)若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)

(3)若再加入fd=2,fd=1,则set变为0001,0011

(4)执行select(6,&set,0,0,0)阻塞等待

(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

 

timeout:

struct timeval{

long tv_sec; // seconds

long tv_usec; // microseconds

}

存在三种情况:

NULL表示仅在有一个描述符准备好I/O时才返回,否则永远等待。

设置值,仅在有一个描述符准备好I/O时才返回,否则等待一段设定的时间。

0,表示检测描述符后立即返回,称为轮询。

 

返回值:

所有描述符集的已就绪的总位数。

 

2.模型表示

 

3.函数使用


#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/time.h>
#include<unistd.h>
#include<string.h>

const int LEN = 1024;
int fds[2];          //只监测标准输入与输出这两个文件描述符
int main()
{

     int std_in = 0;
     int std_out = 1;
     int fds_max = 1;
     fd_set reads, writes;
     struct timeval timeout;
 
     fds[0] = std_in;
     fds[1] = std_out;
 
     while(1)
     {
         FD_ZERO(&reads);
         FD_ZERO(&writes);
         FD_SET(std_in, &reads);          //标准输入关注的是读事件:reads这个集合中, 00000001
         FD_SET(std_out, &writes);        //标准输出关注的是写事件 :writes这个集合中,00000010
         timeout.tv_sec = 5;
         timeout.tv_usec = 0;
         switch( select(fds_max + 1, &reads, &writes, NULL, &timeout))
         {
             case 0:
                 printf("select time out ......\n");
                 break;
             case -1:
                 perror("select");
                 break;
             default:
                 if(FD_ISSET(fds[0], &reads))       //可以从标准输入中读,判断,当std_in上发生事件,则reads为00000001,则满足FD_ISSET判断
                 {
                     char buf[LEN];
                     memset(buf, '\0', LEN);
                     //getns(buf);
					 scanf("%s",buf);
                     printf("echo: %s\n", buf);      //读取后回显

                     if(strncmp(buf, "quit", 4) == 0) //退出
                     {
                         exit(0);
                     }
                 }
                 if(FD_ISSET(fds[1], &writes))//判断,当std_out上发生事件,则writes为00000010,则满足
                 {
                     char* buf = "write is ready.......\n";
                     printf("%s", buf);
                     sleep(5);//等待输入
                 }
                 break;
         }
     }
 
 
 }

运行结果:

toney@sw2:~/study/network$ ./a.out 
write is ready.......
123

echo: 123
write is ready.......
^C

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值