网络编程中一个很重要的函数,没有整理,直接转过来,讲的还是蛮详细的。

转自:http://blog.csdn.net/zhw888888/archive/2009/03/29/4034515.aspx

Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是

习惯写诸如connect、 accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或

是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返

回)。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要

等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相

同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程

序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。下面详细介绍一下!

Select的函数格式(我所说的是Unix系统下的伯克利socket编程,和windows下的有区别,一会儿说明):

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

先说明两个结构体:

第一,struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor),即文件句

柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,

所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来

操作,比如清空集合 FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set *),将

一个给定的文件描述符从集合中删除FD_CLR(int ,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。一会儿举例说明。

第二,struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒

数。具体解释select的参数:

int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!

在Windows中这个参数的值无所谓,可以设置不正确。

fd_set *readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述

符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返

回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出

timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。

fd_set *writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述

符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返

回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出

timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。

fd_set *errorfds同上面两个参数的意图,用来监视文件错误异常。

struct timeval* timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第

一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某

个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符

是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就

是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎

样一定返回,返回值同上述。

返回值:

负值:select错误 正值:某些文件可读写或出错 0:等待超时,没有可读写或错误的文件

在有了select后可以写出像样的网络程序来!举个简单的例子,就是从网络上接受数据写入一个文件中。

例子:

main()

{

int sock;

FILE *fp;

struct fd_set fds;

struct timeval timeout={3,0}; //select等待3秒,3秒轮询,要非阻塞就置0

char buffer[256]={0}; //256字节的接收缓冲区

while(1)

{

FD_ZERO(&fds); //每次循环都要清空集合,否则不能检测描述符变化

FD_SET(sock,&fds); //添加描述符

FD_SET(fp,&fds); //同上

maxfdp=sock>fp?sock+1:fp+1; //描述符最大值加1

switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select使用

{

case -1: exit(-1);break; //select错误,退出程序

case 0:break; //再次轮询

default:

if(FD_ISSET(sock,&fds)) //测试sock是否可读,即是否网络上有数据

{

recvfrom(sock,buffer,256,.....);//接受网络数据

if(FD_ISSET(fp,&fds)) //测试文件是否可写

fwrite(fp,buffer...);//写入文件

buffer清空;

}// end if break;

}// end switch

}//end while

}//end main

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhw888888/archive/2009/03/29/4034515.aspx

select函数详解的更多相关文章

  1. linux select函数详解

    linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...

  2. linux select函数详解【转】

    转自:http://www.cnblogs.com/ccsccs/articles/4224253.html 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数 ...

  3. IO多路复用模型之select()函数详解

    IO复用 我们首先来看看服务器编程的模型,客户端发来的请求服务端会产生一个进程来对其进行服务,每当来一个客户请求就产生一个进程来服务,然而进程不可能无限制的产生,因此为了解决大量客户端访问的问题,引入 ...

  4. select函数详解(转)

    Select函数在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv或recvfrom这样的阻塞 ...

  5. select函数详解及应用

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv或recvfrom这样的阻塞程序 ...

  6. select()函数详解

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是 习惯写诸如connect. accept.recv或recvfrom这样的阻塞程 ...

  7. Linux C select函数详解

    select IO复用机制: http://www.cnblogs.com/hjslovewcl/archive/2011/03/16/2314330.html http://blog.csdn.ne ...

  8. Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt

    PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...

  9. MYSQL常用内置函数详解说明

    函数中可以将字段名当作变量来用,变量的值就是该列对应的所有值:在整理98在线字典数据时(http://zidian.98zw.com/),有这要一个需求,想从多音字duoyinzi字段值提取第一个拼音 ...

随机推荐

  1. centOS初了解--***安装node

    在***买了一个VPS,用了差不多一年了,除了做FQ使用之外,同时也下载了一个node,用了express搭建了一个服务,同时我在博客园有博客,我也懒得转来转去了,直接做了一个重定向,跳转到了博客园. ...

  2. 【PGP公钥】

    Fingerprint: 37AF 3814 3ABC 5DFA 97F5 300E 581D A2E3 F4D2 F585 Key ID:0x581DA2E3F4D2F585 -----BEGIN ...

  3. 使用IDEA将本地项目上传到GitHub

    00.首先保证git和github能够使用ssh连接. 01.在GitHub上新建仓库 需要注意的是不要勾选Initialize this repository with a README. 02.在 ...

  4. IntelliJ IDEA 12详细开发教程(一)思想的转变与新手入门【转】

    转载地址:http://bangqu.com/alicas/blog/433 从事软件开发工作以来,提高自己的开发效率,提高自己编码的规范,提高编码深度层次,这三样一直都是自己努力去追求的事情. 最近 ...

  5. 课时68.id选择器(掌握)

    1.什么是id选择器? 作用:根据指定的id名称找到对应的标签,然后设置属性 格式: #id名称{ 属性:值; } 注意点: 1.每个html标签都有一个属性叫做id,也就是说每个标签都可以设置id ...

  6. Laravel系列 Web

    一.Homestead准备 上一篇文章已经对它的配置进行了说明,下面对Homestead.yaml进行说明 --- ip: "192.168.10.10" memory: 2048 ...

  7. perl语言入门总结-第3章-列表与数组

    1-列表list指的是标题的有序集合, 而数组(array)则是存储列表的变量. 更精确地说,列表指的是数据,而数组指的是变量. 访问数组中的元素 ] = "yabba"; ] = ...

  8. Android 使用Retrofit2.0+OkHttp3.0实现缓存处理+Cookie持久化第三方库

    1.Retrofit+OkHttp的缓存机制 1.1.第一点 在响应请求之后在 data/data/<包名>/cache 下建立一个response 文件夹,保存缓存数据. 1.2.第二点 ...

  9. saltstack plug in

    目录 可插拔的子系统 灵活性 虚拟模块 salt的核心架构提供了一种高速的交流总线,在核心架构的上层,salt暴露出来的特征是:松散耦合,可插拔的子系统. 可插拔的子系统 salt包含20中插件系统, ...

  10. pocscan扫描框架的搭建

    0x00 无意中看到了一篇文章 讲pocscan的搭建..就比较心动 决定自己也搭建一个这样的扫描平台 0x01 安装docker 用的是ubuntu yklin 16.04 x64的系统 在更新源之 ...