ImageVerifierCode 换一换
格式:DOC , 页数:8 ,大小:53KB ,
资源ID:7034697      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7034697.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(WinSocket模型的探讨——完成端口模型.doc)为本站上传会员【xrp****65】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

WinSocket模型的探讨——完成端口模型.doc

1、WinSocket模型的探讨——完成端口模型 众所皆知,完成端口是在WINDOWS平台下效率最高,扩展性最好的IO模型,特别针对于WINSOCK的海量连接时,更能显示出其威力。其实建立一个完成端口的服务器也很简单,只要注意几个函数,了解一下关键的步骤也就行了。 这是篇完成端口入门级的文章,分为以下几步来说明完成端口: 函数 常见问题以及解答 步骤 例程 1、函数: 我们在完成端口模型下会使用到的最重要的两个函数是: CreateIoCompletionPort、GetQueuedCompletionStatus CreateIoCompletion

2、Port 的作用是创建一个完成端口和把一个IO句柄和完成端口关联起来: // 创建完成端口 HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // 把一个IO句柄和完成端口关联起来,这里的句柄是一个socket 句柄 CreateIoCompletionPort((HANDLE)sClient, CompletionPort, (DWORD)PerHandleData, 0); 其中第一个参数是句柄,可以是文件句柄、SOCKET句柄。 第二个就是我们上面创

3、建出来的完成端口,这里就把两个东西关联在一起了。 第三个参数很关键,叫做PerHandleData,就是对应于每个句柄的数据块。我们可以使用这个参数在后面取到与这个SOCKET对应的数据。 最后一个参数给0,意思就是根据CPU的个数,允许尽可能多的线程并发执行。 GetQueuedCompletionStatus 的作用就是取得完成端口的结果: // 从完成端口中取得结果 GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&P

4、erIoData, INFINITE) 第一个参数是完成端口 第二个参数是表明这次的操作传递了多少个字节的数据 第三个参数是OUT类型的参数,就是前面CreateIoCompletionPort传进去的单句柄数据,这里就是前面的SOCKET句柄以及与之相对应的数据,这里操作系统给我们返回,让我们不用自己去做列表查询等操作了。 第四个参数就是进行IO操作的结果,是我们在投递 WSARecv / WSASend 等操作时传递进去的,这里操作系统做好准备后,给我们返回了。非常省事!! 个人感觉完成端口就是操作系统为我们包装了很多重叠IO的不爽的地方,让我们可以更方便的去使用,下篇我

5、将会尝试去讲述完成端口的原理。 2、常见问题和解答 a、什么是单句柄数据(PerHandle)和单IO数据(PerIO) 单句柄数据就是和句柄对应的数据,像socket句柄,文件句柄这种东西。 单IO数据,就是对应于每次的IO操作的数据。例如每次的WSARecv/WSASend等等 其实我觉得PER是每次的意思,翻译成每个句柄数据和每次IO数据还比较清晰一点。 在完成端口中,单句柄数据直接通过GetQueuedCompletionStatus 返回,省去了我们自己做容器去管理。单IO数据也容许我们自己扩展OVERLAPPED结构,所以,在这里所有与应用逻辑有

6、关的东西都可以在此扩展。 b、如何判断客户端的断开 我们要处理几种情况 1) 如果客户端调用了closesocket,我们就可以这样判断他的断开: if(0 == GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, 。。。) { } if(BytesTransferred == 0) { // 客户端断开,释放资源 } 2) 如果是客户端直接退出,那就会出现64错误,指定的网络名不可再用。这种情况我们也要处理的: if(0 == GetQueuedCompletionS

7、tatus(。。。)) { if( (GetLastError() == WAIT_TIMEOUT) || (GetLastError() == ERROR_NETNAME_DELETED) ) { // 客户端断开,释放资源 } } 3、步骤 编写完成端口服务程序,无非就是以下几个步骤: 1、创建一个完成端口 2、根据CPU个数创建工作者线程,把完成端口传进去线程里 3、创建侦听SOCKET,把SOCKET和完成端口关联起来 4、创建PerIOData,向连接进来的SOCKET投递WSARecv操作

8、 5、线程里所做的事情: a、GetQueuedCompletionStatus,在退出的时候就可以使用PostQueudCompletionStatus使线程退出 b、取得数据并处理 4、例程 下面是服务端的例程,可以使用《WinSocket模型的探讨——Overlapped模型(一)》中的客户端程序来测试次服务端。稍微研究一下,也就会对完成端口模型有个大概的了解了。 /* 完成端口服务器 接收到客户端的信息,直接显示出来 */ #include "winerror.h" #include "Winsock2.h" #pra

9、gma comment(lib, "ws2_32") #include "windows.h" #include using namespace std; /// 宏定义 #define PORT 5050 #define DATA_BUFSIZE 8192 #define OutErr(a) cout << (a) << endl \ << "出错代码:" << WSAGetLastError() << endl \ << "出错文件:" << __FILE__ << endl \ <<

10、"出错行数:" << __LINE__ << endl \ #define OutMsg(a) cout << (a) << endl; /// 全局函数定义 /////////////////////////////////////////////////////////////////////// // // 函数名 : InitWinsock // 功能描述 : 初始化WINSOCK // 返回值 : void // //////////////////////////////////////////////////

11、///////////////////// void InitWinsock() { // 初始化WINSOCK WSADATA wsd; if( WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { OutErr("WSAStartup()"); } } /////////////////////////////////////////////////////////////////////// // // 函数名 : BindServerOverlapped // 功能描述 : 绑定端口,并返回一个

12、 Overlapped 的Listen Socket // 参数 : int nPort // 返回值 : SOCKET // /////////////////////////////////////////////////////////////////////// SOCKET BindServerOverlapped(int nPort) { // 创建socket SOCKET sServer = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

13、 // 绑定端口 struct sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_port = htons(nPort); servAddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sServer, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) { OutErr("bind Failed!"); return NULL; } // 设置监听队列为200

14、 if(listen(sServer, 200) != 0) { OutErr("listen Failed!"); return NULL; } return sServer; } /// 结构体定义 typedef struct { OVERLAPPED Overlapped; WSABUF DataBuf; CHAR Buffer[DATA_BUFSIZE]; } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA; typedef struct {

15、SOCKET Socket; } PER_HANDLE_DATA, * LPPER_HANDLE_DATA; DWORD WINAPI ProcessIO(LPVOID lpParam) { HANDLE CompletionPort = (HANDLE)lpParam; DWORD BytesTransferred; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; while(true) { if(0 == GetQueuedComp

16、letionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&PerIoData, INFINITE)) { if( (GetLastError() == WAIT_TIMEOUT) || (GetLastError() == ERROR_NETNAME_DELETED) ) { cout << "closing socket" << PerHandleData->Socket << endl; closesocket(Per

17、HandleData->Socket); delete PerIoData; delete PerHandleData; continue; } else { OutErr("GetQueuedCompletionStatus failed!"); } return 0; } // 说明客户端已经退出 if(BytesTransferred == 0) { cout << "closing socket" << PerHandleData->Socket << e

18、ndl; closesocket(PerHandleData->Socket); delete PerIoData; delete PerHandleData; continue; } // 取得数据并处理 cout << PerHandleData->Socket << "发送过来的消息:" << PerIoData->Buffer << endl; // 继续向 socket 投递WSARecv操作 DWORD Flags = 0; DWORD dwRecv = 0; ZeroMemory(PerIoData

19、 sizeof(PER_IO_OPERATION_DATA)); PerIoData->DataBuf.buf = PerIoData->Buffer; PerIoData->DataBuf.len = DATA_BUFSIZE; WSARecv(PerHandleData->Socket, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); } return 0; } void main() { InitWinsock(); HANDLE Com

20、pletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // 根据系统的CPU来创建工作者线程 SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); for(int i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++) { HANDLE hProcessIO = CreateThread(NULL, 0, ProcessIO, CompletionPort, 0, NULL

21、); if(hProcessIO) { CloseHandle(hProcessIO); } } // 创建侦听SOCKET SOCKET sListen = BindServerOverlapped(PORT); SOCKET sClient; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; while(true) { // 等待客户端接入 //sClient = WSAAccept(sListen, NULL, NU

22、LL, NULL, 0); sClient = accept(sListen, 0, 0); cout << "Socket " << sClient << "连接进来" << endl; PerHandleData = new PER_HANDLE_DATA(); PerHandleData->Socket = sClient; // 将接入的客户端和完成端口联系起来 CreateIoCompletionPort((HANDLE)sClient, CompletionPort, (DWORD)PerHandleData, 0);

23、 // 建立一个Overlapped,并使用这个Overlapped结构对socket投递操作 PerIoData = new PER_IO_OPERATION_DATA(); ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA)); PerIoData->DataBuf.buf = PerIoData->Buffer; PerIoData->DataBuf.len = DATA_BUFSIZE; // 投递一个WSARecv操作 DWORD Flags = 0; DWORD dwRecv

24、 = 0; WSARecv(sClient, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); } DWORD dwByteTrans; PostQueuedCompletionStatus(CompletionPort, dwByteTrans, 0, 0); closesocket(sListen); } 好了,本篇文章就到此为止,以后有时间再继续写下一篇,下篇就不是这种步骤和函数的说明了,而是包括了封装、架构、应用等等方面的技术。OK,下次再会! 本文来自CSDN博客,转载请标明出处:

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服