理解IOCP(完成端口)_第1页
理解IOCP(完成端口)_第2页
理解IOCP(完成端口)_第3页
理解IOCP(完成端口)_第4页
理解IOCP(完成端口)_第5页
免费预览已结束,剩余4页可下载查看

付费下载

下载本文档

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

文档简介

1、理解 I/O Completion Port(完成端口 )欢迎阅读此篇IOCP教程。我将先给岀IOCP的定义然后给岀它的实现方法,最后剖析一个 Echo程序来为您拨开IOCP的谜云,除去你心中对 IOCP的烦恼。OK,但我不能保证你明白IOCP的一切,但我会尽我最大的努力。以下是我会在这篇文章中提到的相关技术:I/O 端口同步/异步堵塞/非堵塞服务端/客户端多线程程序设计Win sock API 2.0在这之前,我曾经开发过一个项目,其中一块需要网络支持,当时还考虑到了代码的可移植性,只要使用select,connect,accept,listen,send还有recv,再加上几个 #ifde

2、f的封装以用来处理Win sock和BSD套接字socket中间的不兼容性,一个网络子系统只用了几个小时很少的代码就写岀来了,至今还让我很回味。那以后很长时间也就没再碰了。前些日子,我们策划做一个网络游戏,我主动承担下网络这一块,想想这还不是小case,心里偷着乐啊。网络游戏好啊,网络游戏为成百上千的玩家提供了乐趣和令人着秘的游戏体验,们在线上互相战斗或是加入队伍去战胜共同的敌人。我信心满满的准备开写我的网络,于是乎,发现过去的阻塞同步模式模式根本不能拿到一个巨量多玩家MMP的架构中去,直接被否定掉了。于是乎,就有了 IOCP,如果能过很轻易而举的搞掂IOCP,也就不会有这篇教程了。下面请诸位

3、跟随我进入正题。什么是IOCP ?先让我们看看对IOCP的评价I/O完成端口可能是 Win32提供的最复杂的内核对象。Adva need Win dows 3rd Jeffrey Richter这是IOCP实现高容量网络服务器的最佳方法。Win dows Sockets2.0:Write Scalable Win sock Apps Usi ng Comp letion PortsMicrosoft Corpo rati onWindows网络编程完成端口模型提供了最好的伸缩性。这个模型非常适用来处理数百乃至上千个套接字。2nd An tho ny Jones & Jim Ohiu ndI/O

4、 compl eti on po rts特别显得重要,因为它们是唯一适用于高负载服务器必须同时维护许多连接线路的一个技术。Completion ports利用一些线程,帮助平衡由I/O请求所引起的负载。这样的架构特别适合用在SMP系统中产生的” scalable服务器。Win32 多线程程序设计Jim Beveridge & Robert Wiener看来我们完全有理由相信IOCP是大型网络架构的首选。那IOCP到底是什么呢?微软在Winsock2中引入了IOCP 这一概念 。IOCP 全称 I/O Completion Port,中文译为I/O完成端口。IOCP是一个异步I/O的API,它可

5、以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,一个套接字socket与一个完成端口关联了起来,然后就可继续进行正常的 Win sock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。这里我要对上面的一些概念略作补充,在解释完成两字之前,我想先简单的提一下同步和而同时一起做两件或两件异步这两个概念, 逻辑上来讲做完一件事后再去做另一件事就是同步,以上事的话就是异步了。你也可以拿单线程和多线程来作比喻。但是我们一定要将同步和堵塞,异步和非堵塞区分开来,所谓的堵塞函数诸如accept(

6、),当调用此函数后,此时线程将挂起,直到操作系统来通知它,” HEY兄弟,有人连进来了 ”,那个挂起的线程将继续进行工作,也就符合”生产者-消费者”模型。堵塞和同步看上去有两分相似,但却是完全不同的概念。大家都知道I/O设备是个相对慢速的设备,不论打印机,调制解调器,甚至硬盘,与CPU相比都是奇慢无比的,坐下来等I/O的完成是一件不甚明智的事情,有时候数据的流动率非常惊人,把数据从你的文件 服务器中以Ethernet速度搬走,其速度可能高达每秒一百万字节,如果你尝试从文件服务器中 读取100KB,在用户的眼光来看几乎是瞬间完成,但是,要知道,你的线程执行这个命令,已I/O。重叠经浪费了 10个

7、一百万次CPU周期。所以说,我们一般使用另一个线程来进行IOoverlapped I/O是Win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这也就是完成的含义。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内部正是以线程来完成overla pped I/O。你可以获得线程所有利益,而不需要付岀什么痛苦的代价。完成端口中所谓的端口 并不是我们在TCP/IP中所提到的端口,可以说是完全没有关系。我到现在也没想通一个I/O设备I/O Device和端口IOCP中的Port有什么关系。估计这个端口也迷惑了不少人。IOCP只不过是用来进行读写操作,

8、和文件 I/O倒是有些类似。既然是一个读写设备,我们所能要求它的只是在处理读与写上的高效。在文章的第三部分你会轻而易举的发现IOCP设计的真正用意。IOCP和网络又有什么关系?int mai n()WSAStartu p(MAKEW0RD(2, 2), &wsaData);Liste nin gSocket = socket(AF_INET, SOCK_STREAM, 0);bin d(Liste nin gSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr);liste n( Liste nin gSocket, 5);int n liste

9、nAddrLe n = sizeof(Clie ntAddr);while(TRUE)NewCo nn ection = acce pt(Liste nin gSocket, (SOCKADDR* )&Clie ntAddr,&n listenAddrLe n);HANDLE hThread = CreateThread(NULL, 0, ThreadFu nc, (void*)NewCo nn ectio n, 0, &dwTreadld);CloseHa ndle(hThread);return 0;相信只要写过网络的朋友,应该对这样的结构在熟悉不过了。accept后线程被挂起,等待一个客

10、户发岀请求,而后创建新线程来处理请求。当新线程处理客户请求时,起初的线程循环回去等待另一个客户请求。处理客户请求的线程处理完毕后终结。在上述的并发模型中,对每个客户请求都创建了一个线程。其优点在于等待请求的线程只需做很少的工作。大多数时间中,该线程在休眠因为recv处于堵塞状态。但是当并发模型应用在服务器端基于Windows NT ,Windows NT 小组注意到这些应用程序的性能没有预料的那么高。特别的,处理很多同时的客户请求意味着很多线程并发地运行在系统中。因为所有这些线程都是可运行的没有被挂起和等待发生什么事 ,Microsoft意识到NT内核花费了太多的时间来转换运行线程的上下文Co

11、ntext,线程就没有得到很多CPU时间来做它们的工作。创建线大家可能也都感觉到并行模型的瓶颈在于它为每一个客户请求都创建了一个新线程。程比起创建进程开销要小,但也远不是没有开销的。我们不妨设想一下:如果事先开好 N个线程,让它们在那hold堵塞,然后可以将所有用户的请求都投递到一个消息队列中去。然后那N个线程逐一从消息队列中去取岀消息并加以处理。就可以避免针对每一个用户请求都开线程。不仅减少了线程的资源,也提高了线程的利用率。理论上很不错,你想我等泛泛之辈都能想岀来的问题,Microsoft又怎会没有考虑到呢?!这个问题的解决方法就是一个称为I/O完成端口的内核对象,他首次在Windows

12、NT3.5 中 被引入。其实我们上面的构想应该就差不多是IOCP的设计机理。其实说穿了 IOCP不就是一个消息队列嘛!你说这和端口 这两字有何联系。我的理解就是IOCP最多是应用程序和操作系统沟通的一个接口罢了。至于IOCP的具体设计那我也很难说得上来,毕竟我没看过实现的代码,但你完全可以进行模拟,只不过性能可能,如果想深入理解IOCP , Jeffrey Ritchter 的Advaneed Windows 3rd其中第13章和第14张有很多宝贵的内容,你可以拿来窥视一下系统是如何完成这一切的。实现方法Microsoft为IOCP提供了相应的 API函数,主要的就两个,我们逐一的来看一下:H

13、ANDLE CreateloCo mp letio nPort (/ han dle to fileHANDLE FileHa ndle.HANDLE Existi ngCo mp letio nPort,/ han dle to I/O comp leti on portULONG _PTR Comp letio nKey,/ comp leti on keyDWORD NumberOfC on curre ntThreads / n umber of threads to execute con curre ntly);在讨论各参数之前,首先要注意该函数实际用于两个截然不同的目的:1 .用

14、于创建一个完成端口对象2 .将一个句柄HANDLE和完成端口关联到一起在创建一个完成一个端口的时候,我们只需要填写一下NumberOfCo ncurre ntThreads这个参数就可以了。它告诉系统一个完成端口上同时允许运行的线程最大数。在默认情况下,所开线程数和CPU数量相同,但经验给我们一个公式:线程数=CPU数* 2 + 2要使完成端口有用,你必须把它同一个或多个设备相关联。这也是调用 CreateIoCo mp letio nPort完成的。你要向该函数传递一个已有的完成端口的句柄,我们既然要处理网络事件,那也就是将客户的socket作为HANDLE传进去。和一个完成键对你有意义的一

15、个 32位值,也就是一个指针,操作系统并不关心你传什么。每当你向端口关联一个设备时,系统向该完成端口的设备列表中加入一条信息纪录。另一个API就是BOOL GetQueuedCo mp letio nStatus(HANDLE Com pl etio nP ort,/ han dle to compl eti on p ortLP DWORD lp NumberOfBytes,/ bytes tran sferredP ULONG _PTR lpComp letio nKey,/ file comp leti on keyLPO VERLA PPED *lp Overla pped,/ buf

16、ferDWORD dwMillisec onds/ op ti onal timeout value);第一个参数指岀了线程要监视哪一个完成端口。很多服务应用程序只是使用一个I/O完成端口,所有的I/O请求完成以后的通知都将发给该端口。简单的说,GetQueuedCo mp leti on Status使调用线程挂起,直到指定的端口的I/O完成队列中岀现了一项或直到超时。同I/O完成端口相关联的第3个数据结构是使线程得到完成I/O项中的信息:传输的字节数,完成键和OVERLAPPED结构的地址。该信息是通过传递给GetQueuedCo mp leti on Satatus的Ip dwNumberOfBytesTra nsferred根据到目前为止已经讲到的东西,IpdwCompletionKey和 IpOverlapped 参数返回给线程的。首先来构建一个frame。

温馨提示

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

最新文档

评论

0/150

提交评论