一.Windows I/O模型之选择(select)模型

时间:2022-03-11 09:06:28

1.选择(select)模型:
选择模型:通过一个fd_set调集打点套接字,在满足套接字需求后,通知套接字。让套接字进行事情。制止套接字进入梗阻模式,,进行无谓的期待。选择模型的核心的FD_SET调集和select函数。通过该函数,我们可以们判断套接字上是否存在数据,或者能否向一个套接字写入数据。

2.select函数:
int select(
    int nfds,//忽略,只是为了兼容而存在。
    fd_set FAR* readfds,//可读性查抄(有数据可读入,连接*,重设,终止)
    fd_set FAR* writefds,//可写性查抄(有数据可发出)
    fd+set FAR* exceptfds,//带外数据查抄(带外数据)
    const struct timeval FAR* timeout//超时
    );

3.select模型的事情法式:
(1)首先把套接字插手到fd_set调集
(2)查抄套接字的可读写性
(3)查抄套接字是否还在fd_set调集上
(4)措置惩罚惩罚数据

4.在三个参数中(readfds、writefds和exceptfds),任何两个都可以是空值;但是,至少有一个不能为空值!最后一个参数timeout对应的是一个指针,它指向一个timeval布局,用于决select最多期待I/O操纵完成多久的时间。如timeout是一个空指针,那么select函数会无限期地“期待下去,直到至少有一个套接字切合指定的条件后返回。select告成完成后,会在fd_set调集中,返回未完成的I/O操纵的套接字句柄的总量。若超时,便会返回0。不管由于什么原因,假如select挪用掉败,城市返回SOCKET_ERROR错误。

5.timeval布局体界说:
struct timeval
{
    long tv_sec;//秒数
    long tv_usec;//毫秒数
};

6.fd_set调集:用select函数对套接字进行监视之前,必需要将套接字分配给一个fd_set调集,设置好读、写以及带外数据的fd_set布局。将一个套接字分配给任何一个调集后,再来挪用select进行监视,便可知道一个套接字上是否正在产生上述的I/O勾当。Winsock供给了下列宏操
作,对fd_set进行措置惩罚惩罚和查抄:
    FD_ZERO(*set):初始化set
    FD_SET(s, *set):将套接字s插手调集set
    FD_CLR(s, *set):从set中删除套接字s。
    FD_ISSET(s,*set):查抄s是否还在调集set上,在挪用select函数之前必需对此进行判断。

7.select模型的事情法式:
(1) 使用FD_ZERO宏,初始化本身感兴趣的每一个fd_set。
(2) 使用FD_SET宏,将套接字句柄分配给本身感兴趣的每个fd_set。
(3) 挪用select函数,期待I/O操纵的完成。
(4) 按照select的返回值,我们便可判断出哪些套接字存在着尚未完成(待决)的I/O操纵,.具体的要领是使用FD_ISSET宏,对每个fd_set调集进行查抄。
(5) 知道了每个调集中“待决”的I/O操纵之后,对I/O进行措置惩罚惩罚,然后返回法式1 ),继续进行select措置惩罚惩罚。
(6)select返回后,它会改削每个fd_set布局,删除那些不存在待决I/O操纵的套接字句柄。这正是我们在上述的法式( 4 )中,为何要使用FD_ISSET宏来判断一个特定的套接字是否仍在调集中的原因。

示例代码:

1 SOCKET s; 2 fd_set fdread; 3 int ret; 4 5 //初始化 6 ... 7 8 //Manage I/O on the socket 9 while(1) 10 { 11 FD_ZERO(&fdread);//初始化调集 12 13 FD_SET(s,&fdread);//添加套接字到调集上 14 15 ret=select(0,&fdread,NULL,NULL,NULL);//挪用select函数监视网络事件的完成情况 16 if(ret==SOCKET_ERROR) 17 { 18 ... 19 } 20 21 if(res>0) 22 { 23 //措置惩罚惩罚数据 24 ... 25 26 if(FD_ISSET(s,&fdread))//查抄套接字是否还在调集上 27 { 28 ... 29 } 30 } 31 32 }

View Code

一.Windows I/O模型之选择(select)模型