第4章 ICOP与可伸缩网络程序_第1页
第4章 ICOP与可伸缩网络程序_第2页
第4章 ICOP与可伸缩网络程序_第3页
第4章 ICOP与可伸缩网络程序_第4页
第4章 ICOP与可伸缩网络程序_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第4章 IOCP与可伸缩网络程序,IOCP(I/O completion port,I/O完成端口)是伸缩性最好的一种I/O模型。,网络通信编程技术与应用,4.1 完成端口I/O模型,WinSock完成端口I/O模型,一般是用在大型的服务程序里面,他的效率和功能是最强大的。如果你的服务程序需要管理几百甚至上千个Socket(海量连接)的话,如Apache,游戏服务器等,你应该采用完成端口I/O模型。 采用完成端口的好处是,操作系统的内部重叠机制可以保证大量的网络请求都被服务器处理,而不是像WSAAsyncSelect 和WSAEventSelect的那样对并发的网络请求有限制。 “完成端口模型

2、是我最喜爱的一种模型。虽然其实现比较复杂(其实我觉得它的实现比用事件通知实现的重叠I/O简单多了),但其效率是惊人的。我在T公司的时候曾经帮同事写过一个邮件服务器的性能测试程序,用的就是完成端口模型。结果表明,完成端口模型在多连接(成千上万)的情况下,仅仅依靠一两个辅助线程,就可以达到非常高的吞吐量。”-一个IT人员的话.,不同I/O模式的性能测试结果:,Windows网络编程模式有好几种,他们各有特点,实现起来复杂程度各不相同,适用范围也不一样。下图是Network Programming for Microsoft Windows 2nd 一书中对不同模式的一个性能测试结果。服务器采用Pe

3、ntium 4 1.7 GHz Xeon的CPU,768M内存;客户端有3台PC,配置分别是Pentium 2 233MHz ,128 MB 内存,Pentium 2 350 MHz ,128 MB内存,Itanium 733 MHz ,1 GB内存。,结果分析大家可以看到:服务器,勿庸置疑,肯定是完成端口模式。那么客户端呢,当然也可以采用完成端口,但是不同模式是在不同的操作系统下支持的,看下图:,完成端口在Windows 98下是不支持的。关键的一点,客户端程序不是用来进行大规模网络响应的,客户端的主要工作应该是进行诸如图形运算等非网络方面的任务。所以,强烈推荐大家使用WSAAsyncSel

4、ect/ WSAEvevtSelect模式实现客户端,因为它实现起来比较直接和容易,而且他完全可以满足客户端编程的需求。,从本质上说,完成端口模型要求我们创建一个Wi n 3 2完成端口对象,通过指定数量的线程,对重叠I / O请求进行管理,以便为已经完成的重叠I / O请求提供服务。 要注意: 所谓“完成端口”,实际是Wi n 3 2、 Windows NT以及Windows 2000采用的一种I / O构造机制. 使用这种模型之前,首先要创建一个I / O完成端口对象,用它面向任意数量的套接字句柄,管理多个I / O请求。 IOCP只不过是用来进行读写操作,和文件I/O有些类似。,实现过程

5、:,以下,分为以下几步来说明完成端口模型: 1。函数 2。常见问题 3。步骤 4。例程,函数,我们在完成端口模型下会使用到的最重要的两个函数是: (1) CreateIoCompletionPort (2) GetQueuedCompletionStatus,(1) CreateIoCompletionPort函数,CreateIoCompletionPort 的作用是:创建一个完成端口对象;把一个IO句柄和完成端口关联起来。 HANDLE CreateIoCompletionPort ( HANDLE FileHandle, /* handle to file*/ HANDLE Existi

6、ngCompletionPort, /* handle to I/O completion port*/ ULONG_PTR CompletionKey, /* completion key*/ DWORD NumberOfConcurrentThreads /* number of threads to execute concurrently*/ );,创建完成端口,通常可以使用以下简单的代码创建完成端口对象,获得完成端口的句柄: HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0

7、);,0表示系统允许的线程数量与处理器一样多。 但经验给我们一个公式: 线程数 = CPU数 * 2 + 2,获得CPU数量的方法: SYSTEM_INFO sysinfo; GetSystemInfo(,HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, sysinfo.dwNumberOfProcessors*2+2 );,把一个IO句柄和完成端口关联起来,这里的句柄是一个socket 句柄,CreateIoCompletionPort( (HANDLE)sClient, Complet

8、ionPort, (DWORD)PerHandleData, 0); 第一个参数是句柄,可以是文件句柄、SOCKET句柄。第二个就是我们上面创建出来的完成端口对象句柄,这里就把sClient和CompletionPort两个东西关联在一起了。第三个参数很关键,叫做PerHandleData(句柄惟一数据),就是对应于每个句柄的数据块。我们可以使用这个参数在后面取到与这个SOCKET对应的任意类型的数据,通常是一个指针。最后一个参数给0,表示系统允许的线程数量与处理器一样多.,(2) GetQueuedCompletionStatus函数,BOOL GetQueuedCompletionStat

9、us( HANDLE CompletionPort, / handle to completion port LPDWORD lpNumberOfBytes, / bytes transferred PULONG_PTR lpCompletionKey, / file completion key LPOVERLAPPED *lpOverlapped, / buffer DWORD dwMilliseconds / optional timeout value ); The function attempts to dequeue an I/O completion packet from a

10、 specified I/O completion port. If there is no completion packet queued, the function waits for a pending I/O operation associated with the completion port to complete.作用就是取得完成端口的结果。,从完成端口中取得结果,第一个参数是完成端口第二个参数是表明这次的操作传递了多少个字节的数据第三个是OUT类型的参数,就是前面CreateIoCompletionPort传进去的单句柄数据,这里就是前面的SOCKET句柄以及与之相对应的

11、数据,(这里操作系统给我们返回,让我们不用自己去做列表查询等操作了)。第四个参数就是进行IO操作的结果,是我们在投递 WSARecv / WSASend 等操作时传递进去的,(这里操作系统做好准备后,给我们返回了。非常省事!),我感觉完成端口就是操作系统为我们包装了很多重叠IO的不爽的地方,让我们可以更方便的去使用。,常见问题,a、什么是句柄惟一数据(PerHandleData)和单IO数据(PerIOData) 句柄惟一数据,即单句柄数据就是和句柄对应的数据,像socket句柄,文件句柄这种东西。 单IO数据,就是对应于每次的IO操作的数据。例如每次的WSARecv/WSASend等 其实我

12、觉得PER是每次的意思,翻译成每个句柄数据和每次IO数据还比较清晰一点。在完成端口中,单句柄数据直接通过GetQueuedCompletionStatus 返回,省去了我们自己做容器去管理。单IO数据也容许我们自己扩展OVERLAPPED结构,所以,在这里所有与应用逻辑有关的东西都可以在此扩展。,b、如何判断客户端的断开。我们要处理几种情况: 1) 如果客户端调用了closesocket,就可以这样判断他的断开: if(0 = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, 。)if(BytesTransferred =

13、 0) / 客户端断开,释放资源 2)如果是客户端直接退出,那就会出现64错误,指定的网络名不可再用。这种情况我们也要处理的: if(0 = GetQueuedCompletionStatus(。) if( (GetLastError() = WAIT_TIMEOUT) | (GetLastError() = ERROR_NETNAME_DELETED) ) / 客户端断开,释放资源 ,实现步骤,一个完成端口大概的处理流程: 1:创建一个完成端口。 2:创建一个线程A。 3:A线程循环调用GetQueuedCompletionStatus()函数来得到IO操作结果,这个函数是个阻塞函数。 4:

14、主线程循环里调用accept等待客户端连接上来。 5:主线程里accept返回新连接建立以后,把这个新的套接字句柄用CreateIoCompletionPort关联到完成端口,然后发出一个异步的WSASend或者WSARecv调用,因为是异步函数,WSASend/WSARecv会马上返回,实际的发送或者接收数据的操作由WINDOWS系统去做。 6:主线程继续下一次循环,阻塞在accept这里等待客户端连接。 7:WINDOWS系统完成WSASend或者WSArecv的操作,把结果发到完成端口。 8:A线程里的GetQueuedCompletionStatus()马上返回,并从完成端口取得刚完成

15、的WSASend/WSARecv的结果。 9:在A线程里对这些数据进行处理(如果处理过程很耗时,需要新开线程处理),然后接着发出WSASend/WSARecv,并继续下一次循环阻塞在GetQueuedCompletionStatus()这里。,其中红线表示是WINDOWS系统进行的处理,不需要我们程序干预。,可创建多个线程,应用举例,1。见completionIO server工程 2。见IOCPDemo工程,归根到底概括完成端口模型一句话:,我们不停地向套接字发出异步的WSASend/ WSARecv IO操作,具体的IO处理过程由WINDOWS系统完成,WINDOWS系统完成实际的IO处理后,把结果送到完成端口上(如果有多个IO都完成了,那么就在完成端口那里排成一个队列)。我们在另外一个线程里从完成端口不断地取出IO操作结果,然后根据需要再发出WSASend/WSARecvIO操作。,注意:,如果你不是做大型的服务程序的话,其他I/O模型就够了。,开发建议:,1. 客户机的开发 建议采用重叠I/O或WSAEventSelect模型,以便在一定程度上提升性能。Windows为基础的应用程序,要进行窗

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论