Winsock—I/O模型之选择模型(一)
Winsock中提供了一些I/O模型帮助应用程序以异步方式在一个或多个套接字上管理I/O。
这样的I/O模型有六种:阻塞(blocking)模型,选择(select)模型,WSAAsyncSelect模型,WSAEventSelect模型,重叠(overlapped)模型,完成端口(completion port)模型。
选择模型:
目的:允许想要避免在套接字调用上阻塞的应用程序有能力管理多个套接字。
一、select函数
select函数可以确定一个或者多个套接字的状态。如果套接字上没有网络事件发生,便进入等待状态,以便执行同步I/O。
1 int select(int nfds, //仅是为了与套接字兼容,忽略
2 fd_set* readfds, //指向一个套接字集合,检查其可读性
3 fd_set* writefds, //检查一个套接字集合,检查其可写性
4 fd_set* exceptfds //指向一个套接字集合,检查错误
5 const struct timeval* timeout //指定函数最长等待时间,如果为NULL,则等待时间为无限长
6 );
函数调用成功,返回发生网络事件的所有的套接字数量的总和。如果超过了时间限制,返回0,失败则返回SOCKET_ERROR。
1、套接字集合
fd_set结构可以把多个套接字连接在一起,形成一个套接字集合。select函数可以测试这个集合中哪些套接字有事件发生。
WINSOCK2.h中的定义如下:
1 typedef struct fd_set{
2 u_int fd_count; //下面数组的大小
3 SOCKET fd_array[FD_SETSIZE]; //套接字句柄数组
4 }
WINSOCK中定义的4个操作fd_set套接字集合的宏:
1 FD_ZERO(*set); //初始化set为空集合。集合使用前应该总是清空。
2 FD_CLR(s,*set); //从set移除套接字s
3 FD_ISSET(s,*set) //检查s是不是set的成员,如果是返回TRUE.
4 FD_SET(s,*set) //添加套接字到集合
2、设置超时
最后的参数timeout是timeval结构的指针,它指定了select函数等待的最长的时间。如果设为NULL,select将会无限阻塞,直到有网络事件发生。
timeval结构定义如下:
1 typedef struct timeval
2 {
3 long tv_sec; //指示等待多少秒
4 long tv_usec; //指示等待多少毫秒
5 }timeval;
服务器端代码:
1 2
3 CInitSock theSock; //初始化Winsock库
4 int main()
5 {
6 USHORT nport = 4567; //此服务器监听的端口号
7 SOCKET sListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
8 sockaddr_in sin;
9 sin.sin_family = AF_INET;
10 sin.sin_port = htons(nPort);
11 sin.sin_addr.S_un.S_addr = INADDR_ANY; //绑定监听套接字到本地
12 if(bind(sListen,(sockaddr*)&sin,sizeof(sin)==SOCKET_ERROR) //绑定套接字失败
13 {
14 printf("Failed bind()n\");
15 return -1;
16 }
17 listen(sListen,5); //进入监听模式
18 fd_set fdSocket; //创建套接字集合
19 FD_ZERO(&fdSocket); //初始化套接字结合
20 FD_SET(&sListen,&fdSocket); //将监听套接字添加进套接字集合中
21 while(TRUE)
22 {
23 fd_set fdRead = fdSocket; //将fdSocket集合拷贝到fdRead
24 int nRet = select(0,&fdRead,NULL,NULL,NULL); //当有事件发生发生时,select函数将移除fdRead集合中没有未决I/O操作的套接字句柄,然后返回。
25 if(nRet>0)
26 {
27 //通过将原来的fdSocket集合与select处理过的fdRead集合比较,确定有哪些套接字有未决I/O,进一步处理这些I/O。
28 for(int i=0;i<(int)fdSocket.fd_count;i++)
29 {
30 if(FD_ISSET(fdSocket.fd_array[i],&fdRead))
31 {
32 if(fdSocket.fd_count<FD_SETSIZE)
33 {
34 sockaddr_in addrRemote;
35 int nAddrLen = sizeof(addrRemote);
36 SOCKET sNew = accept(sListen,(SOCKADDR*)&addrRemote,&nAddrlen);
37 FD_SET(sNew,&fdSocket);
38 printf("接收到连接(%s)\n",inet_ntoa(addrRemote.sin_addr));
39 }
40 else
41 {
42 printf("Too Much Connections!");
43 continue;
44 }
45 }
46 else
47 {
48 char szText[256];
49 int nRecv = recv(fdSocket.fd_array[i],szText,strlen(szText),0); //接收
50 if(nRecv>0)
51 {
52 szText[nRecv] = '\0';
53 printf("接收到数据:%s\n",szText);
54 }
55 else
56 {
57 closesocket(fdRead.fd_array[i]);
58 FD_CLR(fdSocket.fd_array[i],&fdSocket);
59 }
60 }
61 }
62 }
63 }
64 else
65 {
66 printf("Failed select()\n");
67 break;
68 }
69 }
70 return 0;
71 }
Winsock—I/O模型之选择模型(一)的更多相关文章
- 网络IO模型-异步选择模型(Delphi版)
其实关于这个模型,网络上也有一个案例说明 老陈使用了微软公司的新式信箱.这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了, ...
- 一.Windows I/O模型之选择(select)模型
1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作.避免套接字进入阻塞模式,进行无谓的等待.选择模型的核心的FD_SET集合和 ...
- windows socket网络编程--事件选择模型
目录 事件选择模型概述 API详解 工作原理 代码实现 事件选择模型概述 Winsock提供了另一种有用的异步事件通知I/O模型--WSAEventSelect模型.这个模型与WSAAsyncSele ...
- ML 04、模型评估与模型选择
机器学习算法 原理.实现与实践——模型评估与模型选择 1. 训练误差与测试误差 机器学习的目的是使学习到的模型不仅对已知数据而且对未知数据都能有很好的预测能力. 假设学习到的模型是$Y = \hat{ ...
- 机器学习如何选择模型 & 机器学习与数据挖掘区别 & 深度学习科普
今天看到这篇文章里面提到如何选择模型,觉得非常好,单独写在这里. 更多的机器学习实战可以看这篇文章:http://www.cnblogs.com/charlesblc/p/6159187.html 另 ...
- windows下的IO模型之选择(select)模型
1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作. 选择模型的核心是FD_SET集合和select函数.通过该函数,我们可以 ...
- ExtJS表格——行号、复选框、选择模型
本篇的内容是为表格添加行号,和复选框,最后谈一下Ext的选择模型.内容比较简单,就直接上代码了.一. 设置行号 行号的设置主要问题在于删除某一行后需要重新计算行号 Ext.onReady(fun ...
- 莫烦python教程学习笔记——利用交叉验证计算模型得分、选择模型参数
# View more python learning tutorial on my Youtube and Youku channel!!! # Youtube video tutorial: ht ...
- DDD:谈谈数据模型、领域模型、视图模型和命令模型
背景 一个类型可以充当多个角色,这个角色可以是显式的(实现了某个接口或基类),也可以是隐式的(承担的具体职责和上下文决定),本文就讨论四个角色:数据模型.领域模型.视图模型和命令模型. 四个角色 数据 ...
随机推荐
- HDU 1525 类Bash博弈
给两数a,b,大的数b = b - a*k,a*k为不大于b的数,重复过程,直到一个数为0时,此时当前操作人胜. 可以发现如果每次b=b%a,那么GCD的步数决定了先手后手谁胜,而每次GCD的一步过程 ...
- Gulp安装笔记
前言 总的来说,玩gulp的流程是这样的: 安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gulpfile.js -> 运行任务 ...
- Git Cannot rebase: You have unstaged changes.
Cannot rebase: You have unstaged changes. 那说明你有修改过的文件git stashgit pull --rebase (每次push之前最好这样做一次)git ...
- Jekens Source Code Management None 源码管理没有Git
jekens安装完成后,在配置中Source Code Management没有Git的选项,只有none,搞了大半天,一直安装插件报错,网上找的各种文章均未能解决我的问题,多次尝试后终于解决了这个问 ...
- Linux/Unix 下自制番茄钟
习惯使用番茄工作法,在Linux上工作时也需要一个番茄钟. 安装一个Linux下番茄钟工作软件? 其实根本没必要,我们可以用Linux下经典的at命令实现一个简单的番茄钟. 安装AT 一般Linux基 ...
- 微信小程序开发(五)开发框架MINA
微信团队为小程序提供的框架命名为MINA应用框架.MINA框架通过封装微信客户端提供的文件系统.网络通信.任务管理.数据安全等基础功能,对上层提供一整套JavaScript API,让开发者能够非常方 ...
- [CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
[CodePlus 2017 11月赛&洛谷P4058]木材 Description 有 n棵树,初始时每棵树的高度为 Hi ,第 i棵树每月都会长高 Ai.现在有个木料长度总量为 S的订单, ...
- oracle常见错误对应代码与含义
本篇文章是对oracle错误代码进行了详细的总结与分析,需要的朋友参考下 ORA-00001: 违反唯一约束条件 (.) ORA-00017: 请求会话以设置跟踪事件 ORA-00018: 超出最大会 ...
- console.dir() 与 console.dirxml() 的使用
在调试JavaScript程序时,有时需要dump某些对象的详细信息.通过手工编写JavaScript代码可以完成这一工作:针对对象的属性进行循环,将循环到的每一个属性值打印出来:可见,这一过程是比较 ...
- python 爬虫简单的demo
''' @author :Eric-chen @contact:809512722@qq.com @time :2018/1/3 17:55 @desc :通过爬取http://movie.douba ...