之所以称其为select模型是因为它主要是使用select函数来管理I/O的。这个模型的设计源于UNIX系统,目的是允许那些想要避免在套接字调用上阻塞的应用程序有能力管理多个套接字。

int select(

int nfds,                                                 // 忽略,仅是为了与Berkeley套接字兼容

fd_set* readfds,                                  // 指向一个套接字集合,用来检查其可读性

fd_set* writefds,                                 // 指向一个套接字集合,用来检查其可写性

fd_set* exceptfds,                              // 指向一个套接字集合,用来检查错误

const struct timeval* timeout           // 指定此函数等待的最长时间,如果为NULL,则最长时间为无限大

);

Select模型是最常见的I/O模型。

使用 int select( int nfds , fd_set FAR* readfds , fd_set FAR* writefds,fd_set FAR* exceptfds,const struct timeval FAR * timeout ) ;

函数来检查你要调用的Socket套接字是否已经有了需要处理的数据。

select包含三个Socket队列,分别代表: readfds ,检查可读性,writefds,检查可写性,exceptfds,例外数据。 timeout是select函数的返回时间。

例如,我们想要检查一个套接字是否有数据需要接收,我们可以把套接字句柄加入可读性检查队列中,然后调用select,如果,该套接字没有数据需要接收, select函数会把该套接字从可读性检查队列中删除掉,所以我们只要检查该套接字句柄是否还存在于可读性队列中,就可以知道到底有没有数据需要接收了。

timeout参数控制select完成的时间。若timeout参数为空指针,则select将一直阻塞到有一个描述字满足条件,否则的话,timeout指向一个timeval结构,其中指定了select调用在返回前等待多长时间。如果timeval为{0,0},则select立即返回,这可用于探询所选套接口的状态,如果处于这种状态,则select调用可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它,举例来说,阻塞钩子函数不应被调用,且WINDOWS套接口实现不应yield。

函数调用成功,返回发生网络事件的所有套接字数量的总和。如果超过了时间限制返回0,失败则返回SOCKET_ERROR。

typedef struct fd_set {

u_int fd_count;                                       // 下面数组的大小

SOCKET fd_array[FD_SETSIZE];       // 套接字句柄数组

} fd_set;

  • FD_ZERO(*set)                            初始化set为空集合。集合在使用前应该总是清空
  • FD_CLR(s, *set)                          从set移除套接字s
  • FD_ISSET(s, *set)                       检查s是不是set的成员,如果是返回TRUE
  • FD_SET(s, *set)                           添加套接字到集合
 
    typedef struct timeval{
                  long tv_sec;                        // 指示等待多少秒
                  long tv_usec;                      // 指示等待多少毫秒
    } timeval;
 
下面给出使用select模式的例子,运行后在4567端口监听,接受客户端连接请求,打印出接收到的数据。(原来单线程也可以管理多个套接字)

//创建服务器套接字 
socket 
//绑定本地地址 
bind 
//进入监听模式 
listen 
//select模式 
//构造fd_set集合 
fd_set fdSocket;    
//清空fd_set集合并将服务器套接字加入 
FD_ZERO(&fdSocket);   
FD_SET(sListen, &fdSocket);   
//循环 
//复制一份fd_set集合并放入select中检测 
fd_set fdRead = fdSocket;   
int nRet = ::select(0, &fdRead, NULL, NULL, NULL);   
//根据select结果进行相应处理(accept read )

总结:通过select模式,实现了监听socket的accept和客户端的read之间,以及各个客户端之间的read,可以不用一直阻塞在那,而是在有相应事件的时候再进行阻塞处理,把accept和read两个长阻塞转化为select一个长阻塞。

     使用select的好处是程序能够在单个线程内同时处理多个套接字连接,这避免了阻塞模式下的线程膨胀问题。但是,添加到fd_set结构的套接字数量是有限制的,默认情况下,最大值是FD_SETSIZE,它在winsock2.h文件中定义为64。为了增加套接字数量,应用程序可以将FD_SETSIZE定义为更大的值(这个定义必须在包含winsock2.h之前出现)。不过,自定义的值也不能超过Winsock下层提供者的限制(通常是1024)。
    另外,FD_SETSIZE的值太大的话,服务器性能就会受到影响。例如有1000个套接字,那么在调用select之前就不得不设置这1000个套接字,select返回之后,又必须检查这1000个套接字。

Winsock IO模型之select模型的更多相关文章

  1. linux下多路复用模型之Select模型

    Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...

  2. Socket I/O模型之select模型

    socket网络编程中有多种常见的I/O模型: 1.blocking阻塞 2.nonblocking非阻塞 3.I/O multiplexing复用 4.signal driven 5.asynchr ...

  3. 【转】Select模型原理

    Select模型原理利用select函数,判断套接字上是否存在数据,或者能否向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据,被迫 ...

  4. Select模型原理

    Select模型原理 利用select函数,推断套接字上是否存在数据,或者是否能向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据, ...

  5. winsock编程select模型

    winsock编程select模型 网络服务端连接数量过多时,为每一个连接申请一个线程会让机器性能急剧下降(大多说是因为线程在用户态和内核态之间切换会占用大量的CPU时间片).为了解决多线程带来的性能 ...

  6. 很幽默的讲解六种Socket IO模型 Delphi版本(自己Select查看,WM_SOCKET消息通知,WSAEventSelect自动收取,Overlapped I/O 事件通知模型,Overlapped I/O 完成例程模型,IOCP模型机器人)

    很幽默的讲解六种Socket IO模型(转)本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教. 一:select模型 二:WSAAsyncSel ...

  7. [编织消息框架][网络IO模型]NIO(select and poll)

    上面测试论证系统内核在read data时会阻塞,如果我们在把第一个阶段解决掉那么性能就会提高 NIO 编程 JDK 1.4中的java.nio.*包中引入新的Java I/O库,其目的是提高速度.实 ...

  8. I/O模型之二:Linux IO模式及 select、poll、epoll详解

    目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...

  9. windows socket编程select模型使用

    int select(         int nfds,            //忽略         fd_ser* readfds,    //指向一个套接字集合,用来检测其可读性       ...

随机推荐

  1. URAL 1233 Amusing Numbers 好题

    参照了nocow上的解法,照搬过来…… 易知一个数X在数列中在另一个数Y前,当且仅当X前缀小于Y或前缀相等X短,那么我们分布考虑,比如对于数48561: 5位上:10000~48560; 4位上:10 ...

  2. Java实现图片压缩代码,图片大小转换

    在很多项目中我们会把上传的图片做处理,比较图片上传过多对服务器的容量和带宽有很多的浪费,如果不是必须的高清图片,我们可以通过代码来做压缩.在我的项目中我们压缩图片的目的是让web页面打开的速度很快,并 ...

  3. NDK(11)Android.mk编译APK模板

    转自 :  http://hubingforever.blog.163.com/blog/static/1710405792011656434982/ 以下仅是使用Android.mk编译APK程序的 ...

  4. ubuntu中apt-get安装与默认路径

    一.apt-get 安装 deb是debian linus的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb或者直接双击此文件 dpkg 是Debian ...

  5. Caused by: 元素类型为 "package" 的内容必须匹配 "(result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)"

    Caused by: 元素类型为 "package" 的内容必须匹配 "(result-types?,interceptors?,default-interceptor- ...

  6. LA 2678 Subsequence

    有一个正整数序列,求最短的子序列使得其和大于等于S,并输出最短的长度. 用数组b[i]存放序列的前i项和,所以b[i]是递增的. 遍历终点j,然后在区间[0, j)里二分查找满足b[j]-b[i]≥S ...

  7. 51nod1262 扔球

    相关讨论里的答案:(by mint_my ) 1.反弹n次,那起点S,每次反弹点,终点S共连接n+1条边,那么原问题变为从S走n+1条边回到S,为令n=n+12.设步长为a条边,gcd(a,n)==1 ...

  8. HDU 1372 Knight Moves【BFS】

    题意:给出8*8的棋盘,给出起点和终点,问最少走几步到达终点. 因为骑士的走法和马的走法是一样的,走日字形(四个象限的横竖的日字形) 另外字母转换成坐标的时候仔细一点(因为这个WA了两次---@_@) ...

  9. 深入理解OpenERP的工作流(Workflow)

    一.工作流定义: <?xml version="1.0"?>  <terp><data>    <record model="w ...

  10. 同步内核缓冲区sync、fsync和fdatasync函数

    转自http://www.2cto.com/os/201409/339460.html 同步内核缓冲区 1.缓冲区简介 人生三大错觉之一:在调用函数write()时,我们认为该函数一旦返回,数据便已经 ...