《ASCE1885的网络编程》の套接字select模型
2010年10月15日
套接字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 conststruct timeval *timeout //用于设置select()函数时的等待时间
);
该函数返回处于就绪状态并且已经包含在fd_set结构中的套接字总数。如果该函数调用超时则返回0。通过该函数,Windows Sockets应用程序可以判断套接字是否存在数据,或者能否向其写入数据。
1)fd_set结构
该结构是一个管理多个套接字的结构体。在该结构体中,fd_count字段指明套接字的数量,fd_array字段保存fd_count个套接字。fd_set最多可以管理64个套接字。
结构原型如下:
typedefstruct 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()函数的等待时间。原型如下:
typedefstruct 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; iSOCKET 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额外负担。
发表评论
-
Memcache Protocol 翻译
2012-01-20 09:10 693Memcache Protocol 翻译 2010 ... -
Winsocket入门教程二:非阻塞式服务器和客户端程序(TCP)
2012-01-20 09:10 1032Winsocket入门教程二:非阻 ... -
C#线程池
2012-01-20 09:10 697C#线程池 2011年06月23日 ... -
my.ini(my.cnf)与mysql优化指南
2012-01-19 14:14 717my.ini(my.cnf)与mysql优化指南 2011年 ... -
并行 .net 应用程序的过去、现在和未来
2012-01-19 14:14 565并行 .net 应用程序的过去、现在和未来 2011年08月 ... -
Grub4dos命令用法
2012-01-19 14:14 720Grub4dos命令用法 2010年06月01日 blo ... -
顶松数字称重显示器
2012-01-19 14:14 1313顶松数字称重显示器 2011年04月29日 杭州顶松自控 ... -
第一章第一节计算机语言C语言基础教程
2012-01-19 14:14 616第一章第一节计算机语言C语言基础教程 2012年01月02日 ... -
HP 蓝屏 STOP: 0x000000A5――the system is not fully ACPI compliant
2012-01-17 04:04 3709HP 蓝屏 STOP: 0x000000A5――the sys ... -
ARM经典100问
2012-01-17 04:04 847ARM经典100问 2011年03月13日 第1章 体系 ... -
MBR的反编译程序
2012-01-17 04:04 733MBR的反编译程序 2011年0 ... -
HOOK API 函数跳转详解
2012-01-17 04:04 2129HOOK API 函数跳转详解 20 ... -
黑莓8330、8830写号,上网,输入法,汉化
2012-01-17 04:03 1341黑莓8330、8830写号,上网,输入法,汉化 2011年1 ... -
粤语文化纵横谈
2012-01-16 02:52 630粤语文化纵横谈 2009年1 ... -
老广人为粤语---广州话写篇文章
2012-01-16 02:52 617老广人为粤语---广州话写篇文章 2011年07月06日 ... -
穗港同心,打响粤语保卫战!
2012-01-16 02:52 572穗港同心,打响粤语保卫战! 2010年07月15日 -
如何学好粤语
2012-01-16 02:51 579如何学好粤语 2010年06月04日 粤语会馆" ... -
写给粤语社的一封信
2012-01-16 02:51 703写给粤语社的一封信 20 ...
相关推荐
asce1885-blogasce1885的博客
此为ASCE的第三代基准模型代码,可供土木工程领域学者使用。
PHASE II OF THE ASCE BENCHMARK STUDY ON SHM
ASCE7-10-建筑物和其他结构最小设计荷载-中文版.pdf
ASCE是土木工程学会的重要期刊。国外期刊投稿主要是latex,该期刊有Latex的投稿模板。
土木工程几个著名期刊ASCE和Science direct中输出格式
希望大家能用得着这个东西!检索时很有用啊
mfc工程,一个可以编辑,选择能实现众多功能的list控件示范工程,
第三代benchmark模型,可用于主动控制算法的比较
ASCE全文数据库培训iGroup公司.ppt
针对美国IASC-ASCE的结构健康监测科研组提出的基准结构进行结构自振频率识别研究.神经网络训练时使用的数据为有限元程序计算所得出,将有损伤结构在环境激励下某点的加速度响应,通过快速傅立叶变换得到的离散频率响应...
ASCE-7-2005-美国荷载规范-(中文版)
考虑3种对称损伤模式和1种非对称损伤模式,对由国际结构控制协会与美国土木工程学会(IASC-ASCE)提出的健康监测Benchmark模型结构第二阶段有斜撑的情况进行模拟分析。结果表明:该方法能够有效地识别出结构损伤单元...
eclipse 配置AmaterasUML时需要的3个jar 包,以及配置文档 http://blog.csdn.net/asce1885/article/details/40744163
ANSI ASCE CI 71-21 Identifying, Quantifying, and Proving Loss of Productivity.pdf
ASCE_7-10美国建筑荷载规范(中文版);.pdf
957/5000 结构安全和结构动力学有许多领域,通常需要计算随机变量函数的前几个统计矩。 通常的近似是泰勒展开法。 这种方法需要计算导数。 为了避免导数的计算,已经提出了概率矩的点估计。 然而,准确度非常低,...
网络工程师英语词汇 AMI Alternate mark inversion 信号交替反转编码 ALU 逻辑运算单元 A/N 字符/数字方式 ACF/VTAM Advanced communication facility/Virtual telecommunication access method APA 图形方式 APPN ...
国ASCE 7-10 《建筑物和其他结构最小设计荷载》 (ASCE 7-10 “Minimum Design Loads for Buildings and Other Structures”)主要内容翻译与介绍 目录 0 规范内容简介1 1 总则7 1.1 适用范围7 1.2 定义和解释7 1.3 ...
ASCE,1980,ww4)提出了一种用于中国海域的新模型“复合极值分布”,然后将该模型用于“飓风的长期分布”中。美国墨西哥湾和大西洋沿岸地区的特征”(OTC.1982)。 2005年的卡特里娜飓风,丽塔飓风和2012年的桑迪...