1.使用
定义集合
fd_set rdset;
清空集合
FD_ZERO( & rdset)
绑定与清除
FD_SET(fdr, &rdset ) , or FD_SET(STDIN_FILENO, &rdset);
FD_CLR ( fdr , &rdset) , or FD_CLR( STDIN_FILENO ,& rdset) ;
select ()监听
int ret = select ( maxfd+1, &rdset ,NULL , NULL , &timeval ) & timeval为监听间隔
最后一个参数 为 NULL为0 ,为一个数 ,对应了不同的iO模型
struct timeval用来代表时间值,有两个成员,一个是秒数,另一个是毫秒数。 若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回
判断响应
FD_ISSET( STDIN_FILENO,&rdset) or FD_ISST( fdr , &rdset) ;
//chat1.c
#include <stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/time.h>
#include<stdlib.h>
#include<strings.h>
#include<string.h>
int main(int argc ,char *agrv[])
{
if ( argc < 3 )
{
perror("error");
}
int fdr = open(agrv[1],O_RDONLY);
int fdw = open(agrv[2],O_WRONLY);
printf("I am chat1 fdr = %d,fdw = %d\n",fdr,fdw);
char buf[128]= {0};
fd_set rdset;
int ret ;
struct timeval timeout;
while( 1 )
{
FD_ZERO(&rdset);
FD_SET(STDIN_FILENO,&rdset);
FD_SET(fdr,&rdset);
bzero(&timeout,sizeof(timeout));
timeout.tv_sec=3;
ret = select (fdr+1,&rdset,NULL,NULL,&timeout);
if ( ret>0 )
{
if((FD_ISSET(STDIN_FILENO,&rdset)))
{
memset(buf,0,sizeof(buf));
ret =read(STDIN_FILENO,buf,sizeof(buf));
if (0==ret)
{
printf("borken up\n");
break;
}
write(fdw,buf,strlen(buf)-1);
}
if (FD_ISSET(fdr,&rdset))
{
memset(buf,0,sizeof(buf));
ret= read(fdr,buf,sizeof(buf));
if(0 ==ret)
{
printf("bye\n");
break;
}
printf("%s\n",buf);
}
}
else{
printf("timeout \n");
}
}
close(fdr);
close(fdw);
printf("Hello world\n");
return 0;
}
//chat2.c
#include <stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/time.h>
#include<stdlib.h>
#include<strings.h>
#include<string.h>
int main(int argc ,char *agrv[])
{
if ( argc < 3 )
{
perror("error");
}
int fdw = open(agrv[1],O_WRONLY);
int fdr = open(agrv[2],O_RDONLY);
printf("I am chat1 fdr = %d,fdw = %d\n",fdr,fdw);
char buf[128]= {0};
fd_set rdset;
while(1)
{
FD_ZERO(&rdset);
FD_SET(STDIN_FILENO,&rdset);
FD_SET(fdr,&rdset);
int ret = select(fdr+1,&rdset,NULL,NULL,NULL);
if (FD_ISSET(STDIN_FILENO,&rdset))
{
memset(buf, 0 , sizeof(buf));
read(STDIN_FILENO,buf,sizeof(buf));
write(fdw,buf,strlen(buf)-1);
}
if (FD_ISSET(fdr,&rdset))
{
memset(buf,0,sizeof(buf));
ret= read(fdr,buf,sizeof(buf));
if (0==ret)
{
printf("byebye\n");
break;
}
printf("%s\n",buf);
}
}
return 0 ;
}
- select 的原理
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
对于select来说最终的两个字是轮询,不断的轮询所有的描述符,来判断是否需要响应,到达并发的目的。
最大监听数量为1024 ,大多数应用场景下,可能只有少数的进程是活跃的而其他的 进程是活跃的,所以呢,这种轮询是一种浪费