- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
网络模型和完成端口
网络模型和完成端口
废话不多说,先从简单的一点一点往深里说。
首先,要理解SOCKET编程,熟悉windows编程的估计都知道socket(xxx) 创建一个socket,可以实现网络通讯,实际上,linux下一样是用socket函数创建套接字,简单说socket是一个标准,并非windows独有。
当然windows也有自己的特色,比如WINDOWS下必须先调用 WSAStartup 而 linux 就不用。
额,扯远了,再说这个,比如我要实现一个TCP的程序,则需要使用 send/recv 这两个函数,OK,这里就有个问题了,用过recv函数的人都知道,recv调用以后会停在那里,这个叫做阻塞,只有当有数据(IO操作)的时候,recv才会返回。这个就是传说中的阻塞模式。
显然,如果我们是一个UI程序(图形界面程序)我们总不会希望我们的程序变成白白的窗口,直到SOCKET返回时候才继续执行,为了解决这个问题,诞生了几种网络模型。
先说最简单的一种,叫 select 模型,为什么叫这个名字,因为这个模型的核心函数就是 select 函数。
select模型有个核心的结构叫做
typedef struct fd_set {
u_int fd_count;
SOCKET fd_array[FD_SETSIZE];
} fd_set;
他的主要思想是将socket全部放入这个结构中,然后select等待若干秒,然后检查某个socket是否还在这个结构中,就知道这个socket是否发生事件(例如读事件)这样,一个线程循环检查就可以管理很多个socket实现一个简单的服务端,select模型虽然很简单,但是应用却很广泛。一般用在需要实现一个简单的服务端或客户端功能,但是又没必要使用比较复杂的模型的时候。
当然,select也有一些致命的缺点,可以看到他管理套接字是用的一个数组,数组大小是 FD_SETSIZE ,在winsock2.h 109行定义了
/*
* Select uses arrays of SOCKETs. These macros manipulate such
* arrays. FD_SETSIZE may be defined by the user before including
* this file, but the default here should be = 64.
*
* CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE
* INCLUDED IN WINSOCK2.H EXACTLY AS SHOWN HERE.
*/
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */
也就是默认情况下最大只能支持64个套接字,当然可以重定义,但是实际上,select 模型处理大量连接的时候就显得无能为力了。
WSAAsyncSelect模型
这个有些地方叫消息套接字模型,因为他的特点就是使用了windows消息机制,顾名思义,就是先要设置一个消息,和消息响应函数,然后当SOCKET有事件的时候,WINDOWS会发送消息到程序。
很明显,这个模型不需要线程去轮询,缺点也很明显,只有GUI程序才能接收消息。
下面就是比较常用和高级的几个模型了,首先是事件模型
WSAEventSelect模型
这个模型的原理就是设置一个事件对象,一般用 WSACreateEvent 创建,然后需要设置事件,我的IOCP类,主listen socket 就是使用这个模型来 accept 连接的。
例如响应
int nRet = WSAEventSelect(m_sListen, m_lsEvent, FD_ACCEPT); // 选择处理 FD_ACCEPT
然后,就是等待事件对象。
// 等待事件
DWORD dwRet = WSAWaitForMultipleEvents(1, pThis-m_lsEvent, FALSE, 1000, FALSE);
if (WSA_WAIT_TIMEOUT == dwRet)
continue;
当然,如果没有事件的时候,wait 返回的是超时,当有事件发生的时候,下一步就需要枚举事件
// 得到网络事件
dwRet = WSAEnumNetworkEvents(pThis-m_sListen, pThis-m_lsEvent, events);
if (SOCKET_ERROR == dwRet) {
continue;
}
if (events.lNetworkEvent
文档评论(0)