套接字Select模型使得Windows Sockets应用程序可以在同一时间内管理和控制多个套接字。该模型的核心是select()函数,在使用该函数时,还需要用到FD_SET、FD_ZERO、FD_ISSET和FD_CLR四个宏。
套接字的select模型,能够使得Windows Sockets应用程序同时对多个套接字进行管理。调用select()函数检查当前各个套接字的当前状态。并且根据该函数的返回值,判断套接字的可读可写性。然后调用相应的Windows
Sockets API,完成数据的发送和接收等。
Select模型是Windows Sockets中最常见的I/O模型,利用select()函数,应用程序可以判断套接字上是否存在数据,或者是否向该套接字写入数据。
在调用recv()函数接收数据之前,先调用select()函数。如果此时系统没有可读数据,那么select()函数会阻塞在这里。当系统存在可读的数据时,该函数返回。此时应用程序可以调用recv()函数接收数据了。
select()函数原型如下:
int select(
__in int nfds,
//忽略,只为了保持和早期Berkeley套接字应用程序的兼容
__inout fd_set *readfds, //具有可读性套接字集合的指针
__inout fd_set *writefds, //具有可写性套接字集合的指针
__inout fd_set *exceptfds, //检查错误套接字集合的指针
__in const
struct timeval *timeout
//用于设置select()函数时的等待时间
);
该函数返回处于就绪状态并且已经包含在fd_set结构中的套接字总数。如果该函数调用超时则返回0。通过该函数,Windows Sockets应用程序可以判断套接字是否存在数据,或者能否向其写入数据。
1)fd_set结构
该结构是一个管理多个套接字的结构体。在该结构体中,fd_count字段指明套接字的数量,fd_array字段保存fd_count个套接字。fd_set最多可以管理64个套接字。
结构原型如下:
typedef
struct fd_set {
u_int fd_count; //套接字数量
SOCKET fd_array[FD_SETSIZE]; //套接字数组
} fd_set;
在程序中使用该结构表示一系列套接字的集合,例如,准备接收数据的套接字集合(可读性集合);准备发送数据的套接字集合(可写性集合)。
当select()函数返回时,会在fd_set结构中返回刚好未完成I/O操作的所有套接字句柄的总量。
readfds参数将包含符合下面任何一个条件的套接字:1)有数据可以读入。此时在该套接字上调用recv()等函数可立即接收到对方的数据;2)连接已经关闭、重设或中止;3)假如已经调用listen()函数,而且一个连接正在建立。那么此时调用accept()函数会成功。
writefds参数将包含符合下面任何一个条件的套接字:1)有数据可以发出。此时在套接字上可以调用send()等函数向对方发送数据;2)如果已经在一个非锁定套接字上调用了connect()函数,且此时连接成功。
exceptfds参数将包含符合下面任何一个条件的套接字:1)如果已经在一个非锁定套接字上调用connect()函数,且此时连接失败;2)有带外(out-of-band,OOB)数据可供读取。
用select()函数对套接字进行监视之前,在应用程序中必须将套接字分配给一个集合。设置可读、可写以及例外的fd_set结构。然后调用select()函数,就可以知道该套接字是否正在发生I/O操作。例如,应用程序欲判断某个套接字是否存在可读数据时,步骤如下:
1)将该套接字加入readfds集合中;2)以readfds为第二个参数调用select()函数;3)当select()函数返回时,应用程序判断该套接字是否仍然存在于readfds集合中;4)如果该套接字存在于readfds集合中,则表明该套接字可读。此时,应用程序调用recv()等函数接收数据。
调用select()函数时,readfds、writefds和exceptfds这3个参数中至少有一个不能设置为NULL。并且,在该非空参数中,必须至少包含一个套接字。否则select()函数将没有任何套接字可以等待。
不管什么原因,加入select()函数调用失败,都会返回SOCKET_ERROR错误代码。
2)timeval结构
该结构用于定义select()函数的等待时间。原型如下:
typedef
struct timeval {
long tv_sec;
//秒
long tv_usec;
//毫秒
} timeval;
调用select()函数时,timeout参数可以取值如下:
1)空指针:select()函数调用会无限期,等到至少有一个套接字符合设置的条件后,该函数返回;2)0:无论是否有套接字符合设置的条件,select()函数都立即返回;3)非0值。
3)宏
Windows Sockets提供了下列宏,可用来针对I/O活动,对fd_set结构进行处理与检查:
FD_CLR(s, *set):从set集合中删除s套接字;
FD_SET(s, *set):将套接字s加入set集合中;
FD_ISSET(s, *set):检查s是否为set集合中的一员,如果是,返回TRUE;
FD_ZERO(*set):将set集合初始化为空集合。
4)select()模型开发步骤
在开发Windows Sockets应用程序时,通过下面步骤完成对套接字的可读可写判断:
1)使用FD_ZERO宏,初始化自己感兴趣的套接字集合fd_set,如FD_ZERO(readfd);
2)使用FD_SET宏,将套接字分配给参与操作的fd_set集合,如FD_SET(s,
readfd);
3)以该fd_set为参数调用select()函数。等待在指定的fd_set集合中,I/O活动设置好这个套接字。select()完成后会返回在所有fd_set集合中设置的套接字句柄总数,并对每个集合进行相应的更新。
4)select()函数成功返回后,使用FD_ISSET宏,对每个fd_set集合进行检查。如FD_ISSET(s,
readfd),如果返回值TRUE,则说明这个套接字可读。
5)调用相应的Windows Sockets API进行数据的接收和发送。
select()函数返回后,会修改每个fd_set结构,删除那些不存在的没有完成的I/O操作的套接字。这也是第四步中使用FD_ISSET宏来判断一个套接字是否仍在集合中的原因。
下面的示例是一个服务器程序使用select模型管理套接字的方法,此前服务器listenSocket套接字处于监听状态,准备接受客户端的连接请求。
SOCKET listenSocket;
//服务器监听套接字
SOCKET acceptSocket;
//接受客户端连接请求套接字
FD_SET socketSet;
//服务器套接字集合
FD_SET writeSet;
//可写套接字集合
FD_SET readSet;
//可读套接字集合
FD_ZERO(&socketSet);
//清空服务器套接字集合
FD_SET(listenSocket, &socketSet);
//加入监听套接字
while(TRUE)
{
FD_ZERO(&readSet); //清空可读套接字集合
FD_ZERO(&writeSet); //清空可写套接字集合
readSet = socketSet;
writeSet = socketSet;
//调用检查套接字状态
if(SOCKET_ERROR == select(0, &readSet, &writeSet, NULL, NULL))
{
//select函数调用失败
printf("select() returned with error %d/n", WSAGetLastError());
return;
}
//检查是否存在客户端的连接请求
if(FD_ISSET(listenSocket, &readSet))
{
//接受客户端请求
if(INVALID_SOCKET != (acceptSocket=accept(listenSocket, NULL, NULL)))
{
FD_SET(acceptSocket, &socketSet); //将该套接字加入服务器套接字集合
}
else
{
printf("accept() failed with error %d/n", WSAGetLastError());
return;
}
}
//遍历所有的套接字
for(int
i=0; i<socketSet.fd_count; i++)
{
SOCKET sAccept = socketSet.fd_array[i];
if(FD_ISSET(sAccept, &readSet))
//该套接字可读
{
//调用输入函数,接收数据
}
if(FD_ISSET(sAccept, &writeSet))
//该套接字可写
{
//调用输出函数,发送数据
}
}
}
优势与不足:
Select模型优势在于可以同时对多个建立起来的套接字进行有序的管理。可以防止应用程序在一次I/O调用过程中,使阻塞模式套接字被迫进入阻塞状态;使非阻塞套接字产生WSAEWOULDBLOCK错误。
select()函数就好像一个消息中心,当消息到来时,通知应用程序接收和发送数据。这使得Windows Sockets应用程序开发人员可以把精力更多地集中在如何处理数据的发送和接收上。
我们可以看到,完成一次I/O操作经历了两次Windows Sockets函数的调用。例如,当接收对方数据时,第一步,调用select()函数等待该套接字的满足条件;第二步,调用recv()函数接收数据。这种结果与在一个阻塞模式的套接字上调用recv()函数是一样的,因此,使用select()函数的Windows
Sockets程序,其效率可能受损。因为每一个Windows Sockets I/O调用都会经过该函数,因而会导致严重的CPU额外负担。
分享到:
相关推荐
asce1885-blogasce1885的博客
此为ASCE的第三代基准模型代码,可供土木工程领域学者使用。
PHASE II OF THE ASCE BENCHMARK STUDY ON SHM
ASCE 使用指南 ASCE(American Society of Civil Engineers)是美国土木工程师协会,成立于1852年,拥有150多年丰厚的历史,是全球土木工程领域的领导者。ASCE为全球最大的土木工程信息知识的出版机构,每年出版...
ASCE LaTeX 指南主要介绍了土木工程学会(American Society of Civil Engineers,简称ASCE)期刊的LaTeX投稿流程和注意事项。由于ASCE期刊接受LaTeX格式的投稿,因此作者需要按照特定的模板和格式要求提交论文。本文...
### ASCE7-10《建筑物和其他结构最小设计荷载》关键知识点解析 #### 一、规范内容简介 美国土木工程师学会(American Society of Civil Engineers, ASCE)发布的ASCE7-10标准《建筑物和其他结构最小设计荷载》,...
ASCE(美国土木工程师学会)和Science Direct是两个知名的学术出版机构,它们都有自己特定的文献引用和输出格式。EndNote是一款流行的文献管理软件,可以帮助研究人员方便地管理和格式化参考文献。 ASCE(American ...
ASCE(American Society of Civil Engineers,美国土木工程师学会)是一个知名的国际专业组织,而"asce.zip_ASCE_list"可能是指一个与ASCE相关的软件开发项目,具体来说,它是一个MFC(Microsoft Foundation Classes...
Adopting ASCE benchmark 模型 120DOF,选取 y 方向的响应,共 8 个,可以通过标准化处理后的数据建立 AR 模型,并确定合适的模型阶次。 在 MATLAB 练习中,确定模型阶数可以通过计算 AIC 值来实现。例如: ```...
总结来说,"Benchmark.rar_benchmark_benchmark三代_benchmark模型_三代benchmark_主动控制"是一个专注于主动控制算法评估的资源包,它提供了一个先进的三代Benchmark模型,用于比较和优化控制策略的性能。...
ASCE 7-10规定了结构荷载的分析要求,包括荷载的分析方法、计算模型、结果解释等方面的要求。 1.3.5 结构抗力的作用 ASCE 7-10规定了结构抗力的作用要求,包括结构抗力的定义、计算方法、影响因素等方面的要求。 ...
ASCE全文数据库是一个由iGroup公司提供的专业资源,主要聚焦于土木工程领域的知识与研究。这个数据库由美国土木工程师协会(American Society of Civil Engineers)出版,该协会成立于1852年,是全球最大的土木工程...
研究者通过建立多层前馈神经网络(BP-ANN)模型,对国内外94个构件的试验数据进行了分析,同时对比了GB50010-2010、ACI-ASCE 352等现行规范的计算结果。研究表明,神经网络模型得出的计算结果与试验值吻合度高,离散...
ASCE-7-2005美国荷载规范中文版知识点总结 ASCE-7-2005美国荷载规范中文版是美国 土木工程师协会(ASCE)发布的一份最小设计荷载规范。该规范涵盖了建筑和其他结构的设计荷载要求,旨在确保建筑和结构的安全和可靠...
根据给定文件信息,本篇文档是关于Android研发工程师高级进阶技能的介绍,涉及了函数响应式编程、Android Support Annotations、RxJava、Android应用性能优化、Fragment使用、依赖注入、ASCE1885动态启发技术等技术...
9. ASCE、ASE等概念通常出现在OSI模型的高层,如会话层和服务层,它们定义了网络服务的接口和操作。 10. ARP(Address Resolution Protocol):地址解析协议,用于将IP地址映射到物理MAC地址,是TCP/IP协议栈中的...
3. **ASCE/ASE/ASK/ARQ**: ASCE (Association Control Service Element) 和 ASE (Application Service Element) 是OSI模型中服务元素的一部分,用于控制和服务于应用程序。ASK (Amplitude Shift Keying) 是幅度移位...
考虑3种对称损伤模式和1种非对称损伤模式,对由国际结构控制协会与美国土木工程学会(IASC-ASCE)提出的健康监测Benchmark模型结构第二阶段有斜撑的情况进行模拟分析。结果表明:该方法能够有效地识别出结构损伤单元...
给定一个ASCE benchmark模型(这里是一个具有120自由度的模型),选取y方向的响应,通过对响应数据进行标准化处理,然后建立AR模型,并通过计算不同阶数的AIC值来确定合适的模型阶数。在提供的示例中,当阶数达到80...