C语言详解select函数的使用_第1页
C语言详解select函数的使用_第2页
C语言详解select函数的使用_第3页
C语言详解select函数的使用_第4页
C语言详解select函数的使用_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C语言详解select函数的使用目录selectselectAPI介绍select代码编译运行select和poll缺点

select

selectAPI介绍

主旨思想:

首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中。调用一个系统函数,监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行I/O操作时,该函数才返回。

a.这个函数是阻塞

b.函数对文件描述符的检测的操作是由内核完成的

在返回时,它会告诉进程有多少(哪些)描述符要进行I/O操作。

//sizeof(fd_set)=128字节1024位,每一个标志位对应一个文件描述符

intselect(intnfds,fd_set*readfds,fd_set*writefds,

fd_set*exceptfds,structtimeval*timeout);

-参数:

-nfds:委托内核检测的最大文件描述符的值+1

-readfds:要检测的文件描述符的读的集合(有数据发送过来),委托内核检测哪些文件描述符的读的属性

-一般检测读操作

-对应的是对方发送过来的数据,因为读是被动的接收数据,检测的就是读缓冲区

-是一个传入传出参数(内核进行对文件描述符标志位检测,检测完后再返回回来;)

检测过程:文件描述符在用户态,1表示文件描述符需要检测,0表示不需要检测;在内核中处理时:只检测文件描述符为1的文件描述符,如果数据发生变化,置为1,不变化置为0,然后返回给用户态。

-writefds:要检测的文件描述符的写的集合,委托内核检测哪些文件描述符的写的属性

-委托内核检测写缓冲区是不是还可以写数据(不满的就可以写)

要检测哪个文件描述符,就将那个标志位置为1;

缓冲区满了将对应文件描述符标志位置为0,有空余的数据可以写,置为1。

-exceptfds:检测发生异常的文件描述符的集合

-timeout:设置的超时时间

structtimeval{

longtv_sec;/*seconds*/

longtv_usec;/*microseconds*/

};

-NULL:永久阻塞,直到检测到了文件描述符有变化

-tv_sec=0tv_usec=0,不阻塞

-tv_sec0tv_usec0,阻塞对应的时间

-返回值

--1:失败

-0:select函数中设置了超时时间,超时时间到了,没有检测到,返回0

-0(n):检测的集合中有n个文件描述符发生了变化

//将参数文件描述符fd对应的标志位设置为0

voidFD_CLR(intfd,fd_set*set);

//判断fd对应的标志位是0还是1,返回值:fd对应的标志位的值,0,返回0,1,返回1

intFD_ISSET(intfd,fd_set*set);

//将参数文件描述符fd对应的标志位,设置为1

voidFD_SET(intfd,fd_set*set);

//fd_set一共有1024bit位,全部初始化为0

voidFD_ZERO(fd_set*set);

先创建检测读的文件描述符集合

fd_setreads;

将3,4,100,101四个文件描述符置为1,表示需要对这些文件描述符进行检测;

接下来调用select函数:

select(101+1,reads,NULL,NULL,NULL);//第一个参数,需要检测的文件描述符+1--(+1才能遍历到101,因为是从0开始的)

将fd_set从内核态拷贝到用户态(由内核帮我们检测),同时假设A,B发送了数据;

A,B对应的文件描述符为3和4;

结果:3和4有数据,置为1,;100和101没有数据,将其1置为0。

修改完之后,再将fd_set从内核态拷到用户态;

用户可以遍历这个集合,找到哪个文件描述符为1,即3和4,就说明有数据了。

select代码

//客户端

#includestdio.h

#includearpa/inet.h

#includestdlib.h

#includeunistd.h

#includestring.h

intmain(){

//创建socket

intfd=socket(PF_INET,SOCK_STREAM,0);

if(fd==-1){

perror("socket");

return-1;

structsockaddr_inseraddr;

inet_pton(AF_INET,"127.0.0.1",seraddr.sin_addr.s_addr);

seraddr.sin_family=AF_INET;

seraddr.sin_port=htons(9999);

//连接服务器

intret=connect(fd,(structsockaddr*)seraddr,sizeof(seraddr));

if(ret==-1){

perror("connect");

return-1;

intnum=0;

while(1){

charsendBuf[1024]={0};

sprintf(sendBuf,"senddata%d",num++);

write(fd,sendBuf,strlen(sendBuf)+1);

//接收

intlen=read(fd,sendBuf,sizeof(sendBuf));

if(len==-1){

perror("read");

return-1;

}elseif(len0){

printf("readbuf=%s\n",sendBuf);

}else{

printf("服务器已经断开连接...\n");

break;

//sleep(1);

usleep(1000);

close(fd);

return0;

}

//服务端

#includestdio.h

#includearpa/inet.h

#includeunistd.h

#includestdlib.h

#includestring.h

#includesys/select.h

intmain(){

//创建socket

intlfd=socket(PF_INET,SOCK_STREAM,0);

structsockaddr_insaddr;

saddr.sin_port=htons(9999);

saddr.sin_family=AF_INET;

saddr.sin_addr.s_addr=INADDR_ANY;

//绑定

bind(lfd,(structsockaddr*)saddr,sizeof(saddr));

//监听

listen(lfd,8);

//创建一个fd_set的集合,存放的是需要检测的文件描述符

fd_setrdset,tmp;//fd_set底层可以表示1024个文件描述符

FD_ZERO(rdset);//初始化

FD_SET(lfd,rdset);//添加需要监听的文件描述符

intmaxfd=lfd;//定义最大文件描述符,作为参数传入select函数中

while(1){

tmp=rdset;//rdset这个不能变,因为内核再检测时,如果没有数据,就会将其变为0,因此,我们需要复制一份。

//调用select系统函数,让内核帮检测哪些文件描述符有数据

intret=select(maxfd+1,tmp,NULL,NULL,NULL);

if(ret==-1){

perror("select");

exit(-1);

}elseif(ret==0){//这里不可能为0,因为设置了永久阻塞NULL,直到检测到文件描述符有数据变化

continue;

}elseif(ret0){//ret只会返回文件描述符发生变化的个数,不知道具体哪个发生了变化,需要遍历查找

//说明检测到了有文件描述符的对应的缓冲区的数据发生了改变

if(FD_ISSET(lfd,tmp)){//lfd为监听文件描述符

//表示有新的客户端连接进来了

structsockaddr_incliaddr;

intlen=sizeof(cliaddr);

intcfd=accept(lfd,(structsockaddr*)cliaddr,len);

//将新的文件描述符加入到集合中,下一次select检测时,需要检测这些通信的文件描述符有没有数据

FD_SET(cfd,rdset);

//更新最大的文件描述符

maxfd=maxfdcfdmaxfd:cfd;

//检测剩余文件描述符有没有数据变化,从lfd+1开始即可

for(inti=lfd+1;i=maxfd;i++){

if(FD_ISSET(i,tmp)){

//说明这个文件描述符对应的客户端发来了数据

charbuf[1024]={0};

intlen=read(i,buf,sizeof(buf));

if(len==-1){

perror("read");

exit(-1);

}elseif(len==0){//说明客户端断开连接

printf("clientclosed...\n");

close(i);//关闭文件描述符

FD_CLR(i,rdset);/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论