如果你想在Windows平台上构建服务器应用,那么I/O模型是你必须考虑的。
Windows操作系统提供了五种I/O模型,分别是:

■ 选择(select);
■ 异步选择(WSAAsyncSelect);
■ 事件选择(WSAEventSelect);
■ 重叠I/O(Overlapped I/O);
■ 完成端口(Completion Port) 。

每一种模型适用于一种特定的应用场景。程序员应该对自己的应用需求非常明确,
综合考虑到程序的扩展性和可移植性等因素,作出自己的选择。
==============================================
█ 选择(select)模型是Winsock中最常见的 I/O模型。核心便是利用 select 函数,实现对 I/O的管理!
利用 select 函数来判断某Socket上是否有数据可读,或者能否向一个套接字写入数据,防止程序在Socket处于阻塞模式中时,
在一次 I/O 调用(如send或recv、accept等)过程中,被迫进入“锁定”状态;同时防止在套接字处于非阻塞模
式中时,产生WSAEWOULDBLOCK错误。

█ select 的函数原型如下:
int select(
  __in          int nfds,
  __in_out      fd_set* readfds,
  __in_out      fd_set* writefds,
  __in_out      fd_set* exceptfds,
  __in          const struct timeval* timeout
);

其中,第一个参数nfds会被忽略。之所以仍然要提供这个参数,只是为了保持与Berkeley套接字兼容。
后面大家看到有三个 fd_set类型的参数:
一个用于检查可读性(readfds),
一个用于检查可写性(writefds),
一个用于例外数据(exceptfds)。

fd_set 结构的定义如下:
typedef struct fd_set {
u_int fd_count;
SOCKET fd_array[FD_SETSIZE];
} fd_set;

#define FD_SETSIZE      64
所以 fd_set 结构中最多只能监视64个套接字。

fdset 代表着一系列特定套接字的集合。其中, readfds 集合包括符合下述任何一个条件的套接字:
● 有数据可以读入。
● 连接已经关闭、重设或中止。
● 假如已调用了listen,而且一个连接正在建立,那么accept函数调用会成功。

writefds 集合包括符合下述任何一个条件的套接字:
● 有数据可以发出。
● 如果已完成了对一个非锁定连接调用的处理,连接就会成功。

exceptfds 集合包括符合下述任何一个条件的套接字:
● 假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败。
● 有带外(Out-of-band,OOB)数据可供读取。

举个例子,假设我们想测试一个套接字是否“可读”,必须将自己的套接字增添到readfds集合中,
然后调用 select 函数并等待其完成。select 完成之后,再次判断自己的套接字是否仍为 readfds 集合的一部分。
若答案是肯定的,则表明该套接字“可读”,可立即着手从它上面读取数据。

在三个参数中(readfds、writefds 和 exceptfds),任何两个都可以是空值( NULL);
但是,至少有一个不能为空值!在任何不为空的集合中,必须包含至少一个套接字句柄;
否则, select 函数便没有任何东西可以等待。最后一个参数 timeout 对应的是一个指针,它指向一个timeval 结构,
用于决定select 最多等待 I/O操作完成多久的时间。如 timeout 是一个空指针,那么 select 调用会无限
期地“锁定”或停顿下去,直到至少有一个描述符符合指定的条件后结束。

对 timeval 结构的定义如下:
tv_sec 字段以秒为单位指定等待时间;
tv_usec 字段则以毫秒为单位指定等待时间。
1秒 = 1000毫秒

若将超时值设置为(0 , 0),表明 select 会立即返回,出于对性能方面的考虑,应避免这样的设置。

█ select 函数返回值:
select 成功完成后,会在 fdset 结构中,返回刚好有未完成的 I/O操作的所有套接字句柄的总量。
若超过 timeval 设定的时间,便会返回0。若 select 调用失败,都会返回 SOCKET_ERROR,
应该调用 WSAGetLastError 获取错误码!

用 select 对套接字进行监视之前,必须将套接字句柄分配给一个fdset的结构集合,
之后再来调用 select,便可知道一个套接字上是否正在发生上述的 I/O 活动。
Winsock 提供了下列宏操作,可用来针对 I/O活动,对 fdset 进行处理与检查:
● FD_CLR(s, *set):从set中删除套接字s。
● FD_ISSET(s, *set):检查s是否set集合的一名成员;如答案是肯定的是,则返回TRUE。
● FD_SET(s, *set):将套接字s加入集合set。
● FD_ZERO( * set):将set初始化成空集合。

例如,假定我们想知道是否可从一个套接字中安全地读取数据,同时不会陷于无休止的
“锁定”状态,便可使用 FDSET 宏,将自己的套接字分配给 fdread 集合,再来调用 select。要
想检测自己的套接字是否仍属 fdread 集合的一部分,可使用 FD_ISSET 宏。采用下述步骤,便
可完成用 select 操作一个或多个套接字句柄的全过程:
1) 使用FDZERO宏,初始化一个fdset对象;
2) 使用FDSET宏,将套接字句柄加入到fdset集合中;
3) 调用 select 函数,等待其返回……select 完成后,会返回在所有 fdset 集合中设置的套接字句柄总数,
并对每个集合进行相应的更新。
4) 根据 select的返回值和 FDISSET宏,对 fdset 集合进行检查。
5) 知道了每个集合中“待决”的 I/O操作之后,对 I/O进行处理,
然后返回步骤1 ),继续进行 select 处理。

WinSock异步IO模型之Select的更多相关文章

  1. WinSock 重叠IO模型

    title: WinSock 重叠IO模型 tags: [WinSock 模型, 网络编程, 重叠IO模型] date: 2018-06-29 20:26:13 categories: Windows ...

  2. python 并发编程 异步IO模型

    异步IO(Asynchronous I/O) Linux下的asynchronous IO其实用得不多,从内核2.6版本才开始引入.先看一下它的流程: 用户进程发起read操作之后,立刻就可以开始去做 ...

  3. Linux 网络编程的5种IO模型:异步IO模型

    Linux 网络编程的5种IO模型:异步IO模型 资料已经整理好,但是还有未竟之业:复习多路复用epoll 阅读例程, 异步IO 函数实现 背景 上一讲< Linux 网络编程的5种IO模型:信 ...

  4. winsock的io模型(终极篇)

    最近在看服务器框架的搭建,看了不少,都是零零碎碎的,觉得看的差不多了,可以写点最后的总结了,然后,竟然发现了这篇文章,总结做的特别好,肯定比我总结写要好多了,所以我也就不写了,直接转吧...... 套 ...

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

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

  6. IO模型,非阻塞IO模型,select实现多路复用

    1. IO阻塞模型 IO问题: 输入输出 我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时, 如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等 将当前进程阻塞住,切换 ...

  7. Winsock IO模型之select模型

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

  8. IO模型与select,poll,epoll

    五种:阻塞,非阻塞,IO复印,信号驱动,异步. select,poll,epoll select: 典型用32个32位的整数表示1024个描述符,并发的局限. poll:功能同上,但数据结构不一样(链 ...

  9. 协程,事件驱动,异步io模型,异步网络框架

    协程是一种用户态的轻量级线程,内核不知道它的存在.协程运行于一个线程中,协程的切换是由用户控制的.线程的切换是由cpu来控制的,而协程的切换是由用户控制的.协程的执行时串行的. select/poll ...

随机推荐

  1. android studio修改新项目package名称

    android项目生成APK发布必须保证package唯一.新项目在已有项目基础上修改就必须修改package名称. 操作如下: 1) 在模块(module)上右键选择Refactor->Ren ...

  2. Http相应代码及获取方法

    1xx(临时响应)用于表示临时响应并需要请求者执行操作才能继续的状态代码. 代码 说明 100(继续) 请求者应当继续提出请求.服务器返回此代码则意味着,服务器已收到了请求的第一部分,现正在等待接收其 ...

  3. JavaScript 教程学习进度备忘(二)

    备忘:之前,只将“JS 教程”学习完毕,这篇记录:“JS HTML DOM ”.“JS 对象”.“JS Window”.“JS 库” 书签:跳过:另外跳过的内容有待跟进 _______________ ...

  4. bzoj1833 digit

    这道题其实挺水,只是写的时候需要想清楚.我的方法是: 1.将[a,b]转化为[0,b+1)-[0,a) 2.预处理出非0的v在区间[0,10^p)出现次数以及0在区间[0,10^p)出现数 3.将一个 ...

  5. 简易nagios安装出现的问题及解决方法

    安装时候所遇到的问题: A 安装PHP的时候报错xml2-config未找到 安装PHP的时候报错:未找到包libxml2 解决方法:安装libxml2包即可,libxml2是php的依赖包,从而需要 ...

  6. Leetcode 210 Course Schedule II

    here are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prere ...

  7. Eclipse中Maven工程缺少Maven Dependencies

    Eclipse在引入Maven工程后,找不到Maven Dependencies.使得代码报错,具体如下图所示: 而正常Maven的工程如下所示: 产生这种现象的原因可能是工程对应的开发环境改变,本地 ...

  8. IIS启动出错解决方法

    IIS出现server application error,最终解决办法2007年10月30日 星期二 20:38Server Application Error The server has enc ...

  9. Chapter 5 Convert Image Set To LevelDB/LMDB

    Caffe中convert_imageset projrct将图像数据转换成Caffe能读取的数据格式leveldb/lmdb 1.添加命令参数 在main函数中添加命令参数,内容和位置如下: #if ...

  10. 《学习OpenCV》练习题第四章第三题b

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" /* *<学习OpenCV ...