IOCP完成端口详解1
完成端口讲解

完成端口一、什么是完成端口从本质上讲,完成端口是一种异步I/O技术,它提供一个内核对象,可以关联多个I/O设备,同时关联一个线程池,线程池中的线程通常处于睡眠状态,当有I/O出现时,完成端口唤醒等待线程队列中的线程进行处理。
完成端口有着良好的伸缩性灵活性以及较高的效率,一般用来创建大型的服务器。
我们知道,一个服务器应用程序结构可以分为串行模式和并发模式。
在串行模式中,一次只能处理一个请求,第二个请求必须等待第一个请求被处理完毕才能开始处理,适合于客户量比较小的情况;在并发模式中,针对每个请求创建一个线程,使得多个请求可以同时得到处理,因而提高了程序的性能。
但是,我们再进一步思考,如果有多个设备同时发出IO请求,那么在并发模式中也必须创建与之相同个数的线程,但是,CPU的个数是有限的,多于CPU个数的可运行线程就没有意义了,系统不得不在多个线程间进行上下文切换,以使得多个线程并发执行,这必然浪费宝贵的CPU周期。
另外,虽然创建线程较进程而言开销要小,但也并不意味着没有开销,尤其当数量比较大的时候。
在完成端口模型中,引入了线程池的概念,在应用程序初始化时创建一个线程池,在没有请求时处于等待状态,当请求完成时唤醒一个线程运行,运行完毕后重新放入线程池中,等待其他请求使用。
由于不必为每个请求创建一个线程,从而减少了线程的数量,省去了运行中途创建线程的开销,进一步提高了程序的性能。
二、完成端口的内部结构由于完成端口也是一个内核对象,故我们看一下它的内部结构。
完成端口对象包含五个不同的数据结构:1、设备列表:表相:设备句柄、完成键。
当调用CreateIoCompletionPort时将设备与完成端口关联起来,同时在该数据结构中创建一项。
每当向完成端口关联一个设备时,系统向该完成端口的设备列表中加入一条信息。
2、/index.php/Main_Page-->: 150%; mso-bidi-font-size: 10.5pt">I/O完成队列:表相:传输的字节数、32位完成键、I/O请求的OVERLAPPED结构指针、错误代码当一个设备的异步I/O请求完成时,系统检测该设备是否关联了一个完成端口,如果是,系统就向该完成端口的I/O完成队列中加入完成的I/O请求项。
完成端口详细解析

关于完成端口(IOCP)的文章汇总- [C/C++]版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明/logs/32007489.html首先讨论一下I/O Completion Ports试图解决什么样的问题。
写一个IO Intensive服务器程序,对每一个客户请求生成一个新的child process/worker thread来处理,每个process/thread使用同步IO,这是最经典古老的解法了。
在这之上的改进是prefork 多个process 或者使用线程池。
(使用process或thread,原理都差不多,thread的context switch花销要比process switch要小。
为了论述简单,下面只讨论线程。
)这种结构的并发性并不高,哪怕你用C++, C甚至汇编来写,效率都不会很高,究其原因,在于两点:一.同步IO,每个线程大多数时间在等IO request的结束。
IO相对于CPU,那是极极慢的。
我翻了翻手里的Computer Architecture, A Quantitative Approach第二版,1996年出的,里面对CPU Register, CPU Cache, RAM, Disk,列的access time如下:Java代码1.Registers: 2-5 nano seconds2.CPU Cache: 3-10 nano seconds3.RAM: 80-400 nano seconds4.Disk: 5000000 nano seconds (5 milli seconds)如今CPU又按照摩尔定律发展了十年后,这个硬盘还是机械式的磁头移来移去读写,尽管如今disk controller都有cache,也在发展,但和CPU相比,差距越来越大。
(谁有最新数据可以贴上来。
)二.生成数量大大超过CPU总数的线程。
这样做有两个弊端,第一是每个线程要占用内存,Windows底下每个thread自己stack的省缺大小为1M,32位程序下一个用户程序最大能利用的内存也就3G,生成3000个线程,内存就没了。
IOCP完成端口与长连接通讯

最近在写一个通讯代理程序的时候使用了IOCP通讯模型,几年前也使用过IOCP,不过当时的程序是基于短连接的,而这次是长连接的,写这个程序的过程中我觉得主要有以下几点值得注意:
1、整个程序的架构:程序由一个Accept线程,n个工作者线程,1个线程池管理线程,n个业务处理线程构成。Accept线程接收客户端连接并投递 WSARecv重叠操作,工作者线程中通过GetQueuedCompletionStatus阻塞收取数据,收取请求数据后将数据放入队列,然后再投递一个WSARecv重叠操作至GetQueuedCompletionStatus阻塞调用,如果是短连接的话,此处就不需要再投递WSARecv重叠操作了,直接调用GetQueuedCompletionStatus收取另一个客户端连接发送过来的数据就可以了。我刚开始也忽略了这一点,导致程序每次只能收取客户端的第一个请求,后面就再也收不到了。
IOCP

完成IO使用总结IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型。
它是应用程序使用线程池处理异步I/O请求的一种机制。
在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求。
这样就有很多的线程并行地运行在系统中。
而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上。
再加上创建新线程的开销比较大,所以造成了效率的低下。
调用的步骤如下:抽象出一个完成端口大概的处理流程:1:创建一个完成端口。
2:创建一个线程A。
3:A线程循环调用GetQueuedCompletionStatus()函数来得到IO操作结果,这个函数是个阻塞函数。
4:主线程循环里调用accept等待客户端连接上来。
5:主线程里accept返回新连接建立以后,把这个新的套接字句柄用CreateIoCompletionPort 关联到完成端口,然后发出一个异步的WSASend或者WSARecv调用,因为是异步函数,WSASend/WSARecv会马上返回,实际的发送或者接收数据的操作由WINDOWS系统去做。
6:主线程继续下一次循环,阻塞在accept这里等待客户端连接。
7:WINDOWS系统完成WSASend或者WSArecv的操作,把结果发到完成端口。
8:A线程里的GetQueuedCompletionStatus()马上返回,并从完成端口取得刚完成的WSASend/WSARecv的结果。
9:在A线程里对这些数据进行处理(如果处理过程很耗时,需要新开线程处理),然后接着发出WSASend/WSARecv,并继续下一次循环阻塞在GetQueuedCompletionStatus()这里。
归根到底概括完成端口模型一句话:我们不停地发出异步的WSASend/WSARecv IO操作,具体的IO处理过程由WINDOWS系统完成,WINDOWS系统完成实际的IO处理后,把结果送到完成端口上(如果有多个IO 都完成了,那么就在完成端口那里排成一个队列)。
DELPHI高性能大容量SOCKET并发

DELPHI高性能大容量SOCKET并发(一):IOCP完成端口例子介绍例子主要包括IOCP控件封装、服务端实现、传输协议和日志、控制、SQL查询、上传、下载等协议实现,并包括一些初步的性能测试结果。
服务端:界面截图如下:提供服务和桌面方式运行,桌面方式可直接打开程序,方便日常调试,可以使用命令行注册或卸载服务,在CMD中输入D:\DEMO\IOCPDemo\Bin\IOCPDemoSvr.exe -install来注册服务,在CMD输入D:\DEMO\IOCPDemo\Bin\IOCPDemoSvr.exe -uninstall来卸载服务。
客户端:界面截图如下:主要实现了服务端日志查看,服务端协议类表查看,SQL语句执行协议,上传、下载协议实现,其中对上传、下载实现了一个多线程同时传,用于测试服务器并发性能。
性能:支持超过2000个链接及以上同时上传文件,不过每个连接上传速度只有1到2K。
支持超过2W个连接同时在线传输命令。
单实例上传下载测试结果:从测试结果可以看出随着发送包增大,速度变快。
这里存在一个风险,就是SOCKET传输失败的次数也会增加。
(二):IOCP完成端口控件封装IOCP完成端口介绍:完成端口模型是Windows平台下SOCKET端口模型最为复杂的一种I/O模型。
如果一个应用程序需要同时管理为数众多的套接字,而且希望随着系统内安装的CPU数量的增多,应用程序的性能也可以线性提升,采用完成端口模型,往往可以达到最佳的系统性能。
完成端口可以管理成千上万的连接,长连接传文件可以支持5000个以上,长连接命令交互可以支持20000个以上。
这么大并发的连接,更需要考虑的是应用场景,按照100M的网卡传输速度12.5MB/S,如果是5000个传文件连接,则每个连接能分到的速度2.56KB/S;如果是20000个命令交互连接,则每个连接分到的吞吐量是655B/S,这种速度的吞吐量对很多应用是不满足,这时就要考虑加大网卡的传输速度或实现水平扩展,这个我们后续会介绍。
IOCP完全解析

DWORD Flags = 0; // 单 I/O 操作数据 LPPER_IO_DATA PerIoData = NULL; PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA)); ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->DataBuf.len = 1024; PerIoData->DataBuf.buf = PerIoData->buffer; PerIoData->OperationType = 0; // read WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL); } /**/////////////////////////////////////////////////////////////////////////// return nRetCode; } /**/////////////////////////////////////////////////////////////////////////// DWORD WINAPI ServerWorkerThread(LPVOID lpParam) { HANDLE CompletionPort = (HANDLE)lpParam; DWORD BytesTransferred; LPOVERLAPPED lpOverlapped; LPPER_HANDLE_DATA PerHandleData = NULL; LPPER_IO_DATA PerIoData = NULL; DWORD SendBytes; DWORD RecvBytes; DWORD Flags; BOOL bRet = FALSE; while (TRUE) { bRet = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (PULONG_PTR) &PerHandleData,
IOCP完成端口详解(10年吐血大总结)

IOCP完成端口超级详解目录:1.完成端口的优点2.完成端口程序的运行演示3.完成端口的相关概念4.完成端口的基本流程5.完成端口的使用详解6.实际应用中应该要注意的地方一.完成端口的优点1. 我想只要是写过或者想要写C/S模式网络服务器端的朋友,都应该或多或少的听过完成端口的大名吧,完成端口会充分利用Windows内核来进行I/O的调度,是用于C/S 通信模式中性能最好的网络通信模型,没有之一;甚至连和它性能接近的通信模型都没有。
2. 完成端口和其他网络通信方式最大的区别在哪里呢?(1) 首先,如果使用“同步”的方式来通信的话,这里说的同步的方式就是说所有的操作都在一个线程内顺序执行完成,这么做缺点是很明显的:因为同步的通信操作会阻塞住来自同一个线程的任何其他操作,只有这个操作完成了之后,后续的操作才可以完成;一个最明显的例子就是咱们在MFC的界面代码中,直接使用阻塞Socket调用的代码,整个界面都会因此而阻塞住没有响应!所以我们不得不为每一个通信的Socket都要建立一个线程,多麻烦?这不坑爹呢么?所以要写高性能的服务器程序,要求通信一定要是异步的。
(2) 各位读者肯定知道,可以使用使用“同步通信(阻塞通信)+多线程”的方式来改善(1)的情况,那么好,想一下,我们好不容易实现了让服务器端在每一个客户端连入之后,都要启动一个新的Thread和客户端进行通信,有多少个客户端,就需要启动多少个线程,对吧;但是由于这些线程都是处于运行状态,所以系统不得不在所有可运行的线程之间进行上下文的切换,我们自己是没啥感觉,但是CPU却痛苦不堪了,因为线程切换是相当浪费CPU时间的,如果客户端的连入线程过多,这就会弄得CPU都忙着去切换线程了,根本没有多少时间去执行线程体了,所以效率是非常低下的,承认坑爹了不?(3) 而微软提出完成端口模型的初衷,就是为了解决这种"one-thread-per-client"的缺点的,它充分利用内核对象的调度,只使用少量的几个线程来处理和客户端的所有通信,消除了无谓的线程上下文切换,最大限度的提高了网络通信的性能,这种神奇的效果具体是如何实现的请看下文。
完成端口

Windows socket之IO完成端口(IOCP)模型开发IO完成端口是一种内核对象。
利用完成端口,套接字应用程序能够管理数百上千个套接字。
应用程序创建完成端口对象后,通过指定一定数量的服务线程,为已经完成的重叠IO操作提供服务。
该模型可以达到最后的系统性能。
完成端口是一种真正意义上的异步模型。
在重叠IO模型中,当Windows socket应用程序在调用WSARecv函数后立即返回,线程继续运行。
另一线程在在完成端口等待操作结果,当系统接收数据完成后,会向完成端口发送通知,然后应用程序对数据进行处理。
为了将Windows打造成一个出色的服务器环境,Microsoft开发出了IO完成端口。
它需要与线程池配合使用。
服务器有两种线程模型:串行和并发模型。
串行模型:单个线程等待客户端请求。
当请求到来时,该线程被唤醒来处理请求。
但是当多个客户端同时向服务器发出请求时,这些请求必须依次被请求。
并发模型:单个线程等待请求到来。
当请求到来时,会创建新线程来处理。
但是随着更多的请求到来必须创建更多的线程。
这会导致系统内核进行上下文切换花费更多的时间。
线程无法即时响应客户请求。
伴随着不断有客户端请求、退出,系统会不断新建和销毁线程,这同样会增加系统开销。
而IO完成端口却可以很好的解决以上问题。
它的目标就是实现高效服务器程序。
与重叠IO相比较重叠IO与IO完成端口模型都是异步模型。
都可以改善程序性能。
但是它们也有以下区别:1:在重叠IO使用事件通知时,WSAWaitForMultipleEvents 只能等待WSA_MAXIMUM_WAIT_EVENTS(64)个事件。
这限制了服务器提供服务的客户端的数量。
2:事件对象、套接字和WSAOVERLAPPED结构必须一一对应关系,如果出现一点疏漏将会导致严重的后果。
完成端口模型实现包括以下步骤:1:创建完成端口2:将套接字与完成端口关联。
3:调用输入输出函数,发起重叠IO操作。
IOCP完成端口原理

本文主要探讨一下windows平台上的完成端口开发及其与之相关的几个重要的技术概念,这些概念都是与基于IOCP的开发密切相关的,对开发人员来讲,又不得不给予足够重视的几个概念:1) 基于IOCP实现的服务吞吐量2)IOCP模式下的线程切换3)基于IOCP实现的消息的乱序问题。
一、IOCP简介提到IOCP,大家都非常熟悉,其基本的编程模式,我就不在这里展开了。
在这里我主要是把IOCP中所提及的概念做一个基本性的总结。
IOCP的基本架构图如下:如图所示:在IOCP中,主要有以下的参与者:--》完成端口:是一个FIFO队列,操作系统的IO子系统在IO操作完成后,会把相应的IO packet放入该队列。
--》等待者线程队列:通过调用GetQueuedCompletionStatus API,在完成端口上等待取下一个IO packet。
--》执行者线程组:已经从完成端口上获得IO packet,在占用CPU进行处理。
除了以上三种类型的参与者。
我们还应该注意两个关联关系,即:--》IO Handle与完成端口相关联:任何期望使用IOCP的方式来处理IO请求的,必须将相应的IO Handle与该完成端口相关联。
需要指出的时,这里的IO Handle,可以是File的Handle,或者是Socket的Handle。
--》线程与完成端口相关联:任何调用GetQueuedCompletionStatus API的线程,都将与该完成端口相关联。
在任何给定的时候,该线程只能与一个完成端口相关联,与最后一次调用的GetQueuedCompletionStatus为准。
二、高并发的服务器(基于socket)实现方法一般来讲,实现基于socket的服务器,有三种实现的方式(thread per request的方式,我就不提了:)):第一、线程池的方式。
使用线程池来对客户端请求进行服务。
使用这种方式时,当客户端对服务器的连接是短连接(所谓的短连接,即:客户端对服务器不是长时间连接)时,是可以考虑的。
IOCP详解

IOCP详解简介: IOCP(I/O Completion Port,I/O完成端⼝)是性能最好的⼀种I/O模型。
它是应⽤程序使⽤线程池处理异步I/O请求的⼀种机制。
IOCP详解IOCP(I/O Completion Port,I/O完成端⼝)是性能最好的⼀种I/O模型。
它是应⽤程序使⽤线程池处理异步I/O请求的⼀种机制。
在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建⼀个线程来应答请求。
这样就有很多的线程并⾏地运⾏在系统中。
⽽这些线程都是可运⾏的,Windows内核花费⼤量的时间在进⾏线程的上下⽂切换,并没有多少时间花在线程运⾏上。
再加上创建新线程的开销⽐较⼤,所以造成了效率的低下。
Windows Sockets应⽤程序在调⽤WSARecv()函数后⽴即返回,线程继续运⾏。
当系统接收数据完成后,向完成端⼝发送通知包(这个过程对应⽤程序不可见)。
应⽤程序在发起接收数据操作后,在完成端⼝上等待操作结果。
当接收到I/O操作完成的通知后,应⽤程序对数据进⾏处理。
完成端⼝其实就是上⾯两项的联合使⽤基础上进⾏了⼀定的改进。
⼀个完成端⼝其实就是⼀个通知队列,由操作系统把已经完成的重叠I/O请求的通知放⼊其中。
当某项I/O操作⼀旦完成,某个可以对该操作结果进⾏处理的⼯作者线程就会收到⼀则通知。
⽽套接字在被创建后,可以在任何时候与某个完成端⼝进⾏关联。
众所皆知,完成端⼝是在WINDOWS平台下效率最⾼,扩展性最好的IO模型,特别针对于WINSOCK的海量连接时,更能显⽰出其威⼒。
其实建⽴⼀个完成端⼝的服务器也很简单,只要注意⼏个函数,了解⼀下关键的步骤也就⾏了。
分为以下⼏步来说明完成端⼝:0) 同步IO与异步IO1) 函数2) 常见问题以及解答3) 步骤4) 例程0、同步IO与异步IO同步I/O⾸先我们来看下同步I/O操作,同步I/O操作就是对于同⼀个I/O对象句柄在同⼀时刻只允许⼀个I/O操作,原理图如下:由图可知,内核开始处理I/O操作到结束的时间段是T2~T3,这个时间段中⽤户线程⼀直处于等待状态,如果这个时间段⽐较短,则不会有什么问题,但是如果时间⽐较长,那么这段时间线程会⼀直处于挂起状态,这就会很严重影响效率,所以我们可以考虑在这段时间做些事情。
在c#使用IOCP(完成端口)的简单示例

在c#使用IOCP(完成端口)的简单示例这次给大家演示一下利用IOCP的在线程间传递数据的例子,顺便打算讲一些细节和注意的地方。
概述:这里主要使用IOCP的三个API,CreateIoCompletionPort,PostQueuedCompletionStatus,GetQueuedCompletionStatus,第一个是用来创建一个完成端口对象,第二个是向一个端口发送数据,第三个是接受数据,基本上用着三个函数,就可以写一个使用IOCP的简单示例。
其中完成端口一个内核对象,所以创建的时候会耗费性能,CPU得切换到内核模式,而且一旦创建了内核对象,我们都要记着要不用的时候显式的释放它的句柄,释放非托管资源的最佳实践肯定是使用Dispose模式,这个博客园有人讲过N次了。
而一般要获取一个内核对象的引用,最好用SafeHandle来引用它,这个类可以帮你管理引用计数,而且用它引用内核对象,代码更健壮,如果用指针引用内核对象,在创建成功内核对象并复制给指针这个时间段,如果抛了ThreadAbortException,这个内核对象就泄漏了,而用SafeHandle去应用内核对象就不会在赋值的时候发生ThreadAbortException。
另外SafeHandle类继承自CriticalFinalizerObject类,并实现了IDispose接口,CLR对CriticalFinalizerObject及其子类有特殊照顾,比如说在编译的时候优先编译,在调用非CriticalFinalizerObject类的Finalize方法后再调用CriticalFinalizerObject类的Finalize类的Finalize方法等。
在win32里,一般一个句柄是-1或者0的时候表示这个句柄是无效的,所以.net有一个SafeHandle的派生类SafeHandleZeroOrMinusOneIsInvalid ,但是这个类是一个抽象类,你要引用自己使用的内核对象或者非托管对象,要从这个类派生一个类并重写Relseas方法。
iocp_1_实现步骤

IOCP 是什么以下就是IOCP的模型图,能看懂么?IOCP模型(图1.1)<一>IOCP实现步骤如果懂得了IOCP的工作原理,它实现起来是很简单的。
它的实现步骤如下:1.创建好IOCP2.创建Socket(socket可以是由Accept得到)3.将Socket关联到IOCP4.socket向IOCP提交各种所需请求5.IOCP操作完成之后将结果返回给socket6.重复步骤3和4 ,直到socket关闭它就那么几个步骤,但实现起来需要不少的代码。
以下就以创建一个客户端的socket为例,先做部分的讲解。
这里主要讲解原理,函数的参数和返回值先忽略。
1.//创建IOCP// 利用函数CreateIoCompletionPort 创建IOCP// 注意参数设置m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,(ULONG_PTR)0,0);// m_hIocp 就代表一个完成端口了2.// 创建连接型的Socket// 利用利用函数WSASocket创建socket,必须指定WSA_FLAG_OVERLAPPEDm_sockClient = ::WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);// m_sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 这样也可以// 默认为WSA_FLAG_OVERLAPPED// 以下的绑定很重要,也是容易漏掉的。
(如果少了绑定,在ConnextEx 时将得到错误代码:10022—提供了一个无效的参数sockaddr_in local_addr;ZeroMemory(&local_addr, sizeof(sockaddr_in));local_addr.sin_family = AF_INET;i nt irt = ::bind(m_sockClient, (sockaddr*)(&local_addr), sizeof(sockaddr_in));// m_sockClient 是创建好的socket3.//将Socket关联到IOCP// 又利用上了CreateIoCompletionPort,它将socket关联到IOCPCreateIoCompletionPort((HANDLE)m_sockClient,m_hIocp,(ULONG_PTR)m_sockClient,0);// 已将sockClient关联到m_hIocp// (ULONG_PTR)m_sockClient 为以后识别是那个socket的操作4.// socket向IOCP提交各种所需请求, 这里提交的是连接请求// 代码比较长,将整个函数都拷贝了过来BOOL CIOCP_ClientDlg::ConnectToServer(){//----------------------LPFN_CONNECTEX m_lpfnConnectEx = NULL;DWORD dwBytes = 0;GUID GuidConnectEx = WSAID_CONNECTEX;// 重点,获得ConnectEx函数的指针if (SOCKET_ERROR == WSAIoctl(m_sockClient, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidConnectEx, sizeof (GuidConnectEx),&m_lpfnConnectEx, sizeof (m_lpfnConnectEx), &dwBytes, 0, 0)){TRACE( "WSAIoctl is failed. Error code = %d", WSAGetLastError());return FALSE;}MYOVERLAPPED *pmyoverlapped = new MYOVERLAPPED; // socket和I/O通讯的载体pmyoverlapped->operateType = OP_CONNECT; // 设置请求类型,得到I/O结果时根据此// //来识别请求类型pmyoverlapped->hEvent = NULL; // 非事件模型// 设置连接目标地址sockaddr_in addrPeer;ZeroMemory(&addrPeer, sizeof(sockaddr_in));addrPeer.sin_family = AF_INET;addrPeer.sin_addr.s_addr = inet_addr( "192.168.0.15" );addrPeer.sin_port = htons( 5400 );int nLen = sizeof(addrPeer);PVOID lpSendBuffer = NULL;DWORD dwSendDataLength = 0;DWORD dwBytesSent = 0;// 重点BOOL bResult = m_lpfnConnectEx(m_sockClient,(sockaddr*)&addrPeer, // [in] 对方地址nLen, // [in] 对方地址长度lpSendBuffer, // [in] 连接后要发送的内容,这里不用dwSendDataLength, // [in] 发送内容的字节数,这里不用&dwBytesSent, // [out] 发送了多少个字节,这里不用(OVERLAPPED*)pmyoverlapped); //[in] 这东西复杂,下一篇有详解if (!bResult ) // 返回值处理{if( WSAGetLastError() != ERROR_IO_PENDING) // 调用失败{TRACE(TEXT("ConnextEx error: %d\n"),WSAGetLastError());return FALSE;}else;//操作未决(正在进行中…){TRACE0("WSAGetLastError() == ERROR_IO_PENDING\n");// 操作正在进行中}}return TRUE;}// 在这个函数中重点是WSAIoctl函数(得到ConnectEx函数地址)和m_lpfnConnectEx 函数指针(进行ConnectEx调用,也就是向I/O提交连接对方的请求)。
完成端口

IOCP模型总结(转)2009-06-26 17:22IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型。
它是应用程序使用线程池处理异步I/O请求的一种机制。
在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求。
这样就有很多的线程并行地运行在系统中。
而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上。
再加上创建新线程的开销比较大,所以造成了效率的低下。
调用的步骤如下:抽象出一个完成端口大概的处理流程:1:创建一个完成端口。
2:创建一个线程A。
3:A线程循环调用GetQueuedCompletionStatus()函数来得到IO操作结果,这个函数是个阻塞函数。
4:主线程循环里调用accept等待客户端连接上来。
5:主线程里accept返回新连接建立以后,把这个新的套接字句柄用CreateIoCompletionPort 关联到完成端口,然后发出一个异步的WSASend或者WSARecv调用,因为是异步函数,WSASend/WSARecv会马上返回,实际的发送或者接收数据的操作由WINDOWS系统去做。
6:主线程继续下一次循环,阻塞在accept这里等待客户端连接。
7:WINDOWS系统完成WSASend或者WSArecv的操作,把结果发到完成端口。
8:A线程里的GetQueuedCompletionStatus()马上返回,并从完成端口取得刚完成的WSASend/WSARecv的结果。
9:在A线程里对这些数据进行处理(如果处理过程很耗时,需要新开线程处理),然后接着发出WSASend/WSARecv,并继续下一次循环阻塞在GetQueuedCompletionStatus()这里。
归根到底概括完成端口模型一句话:我们不停地发出异步的WSASend/WSARecv IO操作,具体的IO处理过程由WINDOWS系统完成,WINDOWS系统完成实际的IO处理后,把结果送到完成端口上(如果有多个IO都完成了,那么就在完成端口那里排成一个队列)。
完成端口详解和EPOLL详解

由图可知,内核开始处理I/O操作到结束的时间段是T2~T3,这个时间 段中用户线程一直处于等待状态,如果这个时间段比较短,则不会有 什么问题,但是如果时间比较长,那么这段时间线程会一直处于挂起 状态,这就会很严重影响效率,所以我们可以考虑在这段时间做些事 情。
• 异步I/O
异步I/O操作则很好的解决了这个问题,它可以使得内核开始处理 I/O操作到结束的这段时间,让用户线程可以去做其他事情,从而提 高了使用效率。
Windows完成端口 Linux Fra bibliotekPOLL 解析
目录
1. Windows完成端口介绍 2. Linux EPOLL介绍
1. Windows完成端口
• 同步I/O与异步I/O 说起完成端口,它的实现机制其实是重叠 I/O实现异步I/O操作,下面就结合同步I/O来 解释下什么是异步I/O。
• 同步I/O 首先我们来看下同步I/O操作,同步I/O操作就是对于同一个I/O对 象句柄在同一时刻只允许一个I/O操作,原理图如下:
• 下面给出两个示例代码,方便大家理解 DWORD nReadByte ; BYTE bBuf[BUF_SIZE] ; OVERLAPPED ov = { 0, 0, 0, 0, NULL } ; // hEvent = NULL ; HANDLE hFile = CreateFile ( ……, FILE_FLAG_OVERLAPPED, …… ) ; ReadFile ( hFile, bBuf, sizeof(bBuf), &nReadByte, &ov ) ; // 由于此时hEvent=NULL,所以同步对象为hFile,下面两句的效果一样 WaitForSingleObject ( hFile, INFINITE ) ; //GetOverlappedResult ( hFile, &ov, &nRead, TRUE ) ; 这段代码在调用ReadFile后会立即返回,但在随后的 WaitForSingleObject或者GetOverlappedResult中阻塞,利用同步对象 hFile进行同步。 这段代码在这里可以实现正常的异步I/O,但存在一个问题,倘若现 在需要对hFile句柄进行多个I/O操作,就会出现问题。
WinSock IO 模型 —- 完成端口模型IOCP

引言:经过三天的努力,我终于把Winsock I/O 模型,做了一个基本了解,最终还把最为复杂高效的CompletionPort(完成端口)模型看懂了,可以说这是一场比较大的胜利。
下面来着重介绍Completion Port(完成端口)。
一、学习前提:1、会winsock 基础编程,也就是说你要明白winsock 的Tcp 和udp编程流程。
2、学习完成端口前最好是先去好好看下重叠I/O 模型,因为完成端口模型,有一部分还是重叠I/O模型的东西,要是不懂那你就歇菜了。
3、会CreateThread 创建线程最好是明白原理。
二、模型特性:在使用一个技术前如果连这个技术的特性都不了解,那你就真是一个….。
1、首先要强调的是完成端口模型是只适合Window NT 或Windows2000 等windows系统,所以在其他系统上用不了。
2、完成端口模型是一种复杂但是可以用时管理数百甚至数千的套接字的一种模型所以当你的系统要同时处理非常多的通信请求完成端口是最好的选择。
3、一般我们使用完成端口的时候都是按照系统CPU数量来创建IO服务线程的,所以如果你的系统cpu数量越多那么性能当然会越好。
三、模型原理:这个模型原理其实是我个人的一个理解和概括,所以不一定完全正确各位看官见谅不要说我坑你了。
其实所谓的完成端口模型就是先创建一个完成端口(注意我们在创建完成端口的时候指定了这个完成端口同时执行的IO服务线程数量,一般为cpu数量),并创建若干(说若干是因为我们一般是根据cpu数量来创建线程的,这样做是因为每个cpu执行一个线程就避免的线程的切换影响效率,但是实际我们还是会创建大于cpu数量一定值的线程,虽然前面指定了完成端口同时执行的线程只有cpu个数,但是因为有的线程会出现挂起的情况,多创建一点就可以减少因为挂起而使cpu闲置)的服务线程(将完成端口作为参数传递给线程)然后将完成端口和我们关心的套接字关联在一起,并且在关联的时候我们还可以传递一个自定义的结构体。
IOCP完成端口详解

IOCP完成端口详解通常要开发网络应用程序并不是一件轻松的事情,不过,实际上只要掌握几个关键的原则也就可以了——创建和连接一个套接字,尝试进行连接,然后收发数据。
真正难的是要写出一个可以接纳少则一个,多则数千个连接的网络应用程序。
本文将讨论如何通过Winsock2在Windows NT 和Windows 2000上开发高扩展能力的Winsock应用程序。
文章主要的焦点在客户机/服务器模型的服务器这一方,当然,其中的许多要点对模型的双方都适用。
API与响应规模通过Win32的重叠I/O机制,应用程序可以提请一项I/O操作,重叠的操作请求在后台完成,而同一时间提请操作的线程去做其他的事情。
等重叠操作完成后线程收到有关的通知。
这种机制对那些耗时的操作而言特别有用。
不过,像Windows 3.1上的WSAAsyncSelect()及Unix下的select()那样的函数虽然易于使用,但是它们不能满足响应规模的需要。
而完成端口机制是针对操作系统内部进行了优化,在Windows NT 和Windows 2000上,使用了完成端口的重叠I/O机制才能够真正扩大系统的响应规模。
完成端口一个完成端口其实就是一个通知队列,由操作系统把已经完成的重叠I/O请求的通知放入其中。
当某项I/O操作一旦完成,某个可以对该操作结果进行处理的工作者线程就会收到一则通知。
而套接字在被创建后,可以在任何时候与某个完成端口进行关联。
通常情况下,我们会在应用程序中创建一定数量的工作者线程来处理这些通知。
线程数量取决于应用程序的特定需要。
理想的情况是,线程数量等于处理器的数量,不过这也要求任何线程都不应该执行诸如同步读写、等待事件通知等阻塞型的操作,以免线程阻塞。
每个线程都将分到一定的CPU时间,在此期间该线程可以运行,然后另一个线程将分到一个时间片并开始执行。
如果某个线程执行了阻塞型的操作,操作系统将剥夺其未使用的剩余时间片并让其它线程开始执行。
[转]IOCP介绍
![[转]IOCP介绍](https://img.taocdn.com/s3/m/5b2159d609a1284ac850ad02de80d4d8d05a0156.png)
[转]IOCP介绍IO完成端⼝下⾯摘抄于MSDN《I/O Completion Ports》,smallfool翻译,原⽂请参考CSDN⽂档中⼼⽂章《I/O Completion Ports》,。
I/O完成端⼝是⼀种机制,通过这个机制,应⽤程序在启动时会⾸先创建⼀个线程池,然后该应⽤程序使⽤线程池处理异步I/O请求。
这些线程被创建的唯⼀⽬的就是⽤于处理I/O请求。
对于处理⼤量并发异步I/O请求的应⽤程序来说,相⽐于在I/O请求发⽣时创建线程来说,使⽤完成端⼝(s)它就可以做的更快且更有效率。
CreateIoCompletionPort函数会使⼀个I/O完成端⼝与⼀个或多个⽂件句柄发⽣关联。
当与⼀个完成端⼝相关的⽂件句柄上启动的异步I/O操作完成时,⼀个I/O完成包就会进⼊到该完成端⼝的队列中。
对于多个⽂件句柄来说,这种机制可以⽤来把多⽂件句柄的同步点放在单个对象中。
(⾔下之意,如果我们需要对每个句柄⽂件进⾏同步,⼀般⽽⾔我们需要多个对象(如:Event来同步),⽽我们使⽤IO Complete Port 来实现异步操作,我们可以同多个⽂件相关联,每当⼀个⽂件中的异步操作完成,就会把⼀个complete package放到队列中,这样我们就可以使⽤这个来完成所有⽂件句柄的同步)调⽤GetQueuedCompletionStatus函数,某个线程就会等待⼀个完成包进⼊到完成端⼝的队列中,⽽不是直接等待异步I/O请求完成。
线程(们)就会阻塞于它们的运⾏在完成端⼝(按照后进先出队列顺序的被释放)。
这就意味着当⼀个完成包进⼊到完成端⼝的队列中时,系统会释放最近被阻塞在该完成端⼝的线程。
调⽤GetQueuedCompletionStatus,线程就会将会与某个指定的完成端⼝建⽴联系,⼀直延续其该线程的存在周期,或被指定了不同的完成端⼝,或者释放了与完成端⼝的联系。
⼀个线程只能与最多不超过⼀个的完成端⼝发⽣联系。
第5章_完成端口

(2)完成端口模型
解决的问题: 当需要管理众多套接字时,应用程序要为每一个套接字开一个
线程,当线程较多时系统效率降低且线程很难管理。
完成端口本质: 事先开辟N个线程,当若干套接字有I/O处理时,利用N个线程对
重叠I/O进行处理。
完成端口 GetQueuedCompletionStatus
N个线程 进行处理
利用完成端口创建程序的步骤: 创建完成端口 确定所需创建的 工作线程数 创建套接字 准备参数
在新连接上开始 I/O,投递一个或 多个请求
接收连接
将新连接关联到 完成端口
完成端口 案例
案例:实现一个Echo服务器
{
OVERLAPPED Overlapped; WSABUF DataBuf; CHAR Buffer[DATA_BUFSIZE]; DWORD BytesSEND; // 发送字节数 DWORD BytesRECV; } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;
完成端口的创建一般需要两次,第一次创建一个没有指定参数的完 成端口对象,第二次再将参数传递。
Comport= CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0) CreateIoCompletionPort((HANDLE) Accept[num_players], Comport, (DWORD) PerHandleData, 0)
投递 绑定 CreateIoCompletionPort
I/O(OS)
发送
Socket
WSASend和WSARecv
HANDLE CreateIoCompletionPort (
IOCP浅析1

什么是IOCP?众所周知,为了绝对同步,所以很多模式都采用的是同步模式,而不是异步,这样就会产生很大情况下在等待,CPU在切换时间片,从而导致效率比较低。
自从MS在winsocket2中引入了IOCP这个模型之后,他才开始被大家所认知。
IOCP (I/O Completion Port),中文译作IO完成端口,他是一个异步I/O操作的API,他可以高效的将I/O事件通知给我们的应用程序,那游戏项目来说,就是客户端或者服务器。
他与Socket基础API select()或其他异步方法不同的是,他需要讲一个Socket和一个完成端口绑定在一起,然后就可以进行网路通信了。
什么是同步/异步?所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。
按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等)。
异步的概念和同步相对。
当一个异步过程调用发出后,调用者不能立刻得到结果。
实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
逻辑上通俗来讲是完成一件事再去做另外一件事情就是同步,而一起做两件或者两件以上的事情就是异步了。
类似于Win32API中的SendMessage()和PostMessage(),你可以将他理解成单线程和多线程的区别。
拿游戏服务器与客户端通信来说:如果是同步:ClientA发送一条Msg1Req消息给Server,这个时候ClientA就会等待Server处理Msg1Req。
这段时间内ClientA只有等待,因为Server还没有给ClientA回复Msg1Ack消息,所以ClientA只能痴痴的等,等到回复之后,才能处理第二条Msg2Req消息,这样无疑就会大大的降低性能,产生非常差的用户体验。
如果是异步:ClientA发送一条Msg1Req消息给Server,ClientA有发送第二条Msg2Req消息给Server,Server会将他们都存入队列,一条一条处理,处理完之后回复给ClientA,这样用户就可以不必等待,效率就会非常高。
理解I O C P(完成端口)

理解I/O Completion Port(完成端口)欢迎阅读此篇IOCP教程。
我将先给出IOCP的定义然后给出它的实现方法,最后剖析一个Echo 程序来为您拨开IOCP的谜云,除去你心中对IOCP的烦恼。
OK,但我不能保证你明白IOCP 的一切,但我会尽我最大的努力。
以下是我会在这篇文章中提到的相关技术:I/O端口同步/异步堵塞/非堵塞服务端/客户端多线程程序设计Winsock API 2.0在这之前,我曾经开发过一个项目,其中一块需要网络支持,当时还考虑到了代码的可移植性,只要使用select,connect,accept,listen,send还有recv,再加上几个#ifdef的封装以用来处理Winsock和BSD套接字[socket]中间的不兼容性,一个网络子系统只用了几个小时很少的代码就写出来了,至今还让我很回味。
那以后很长时间也就没再碰了。
前些日子,我们策划做一个网络游戏,我主动承担下网络这一块,想想这还不是小case,心里偷着乐啊。
网络游戏好啊,网络游戏为成百上千的玩家提供了乐趣和令人着秘的游戏体验,他们在线上互相战斗或是加入队伍去战胜共同的敌人。
我信心满满的准备开写我的网络,于是乎,发现过去的阻塞同步模式模式根本不能拿到一个巨量多玩家[MMP]的架构中去,直接被否定掉了。
于是乎,就有了IOCP,如果能过很轻易而举的搞掂IOCP,也就不会有这篇教程了。
下面请诸位跟随我进入正题。
什么是IOCP?先让我们看看对IOCP的评价I/O完成端口可能是Win32提供的最复杂的内核对象。
[Advanced Windows 3rd] Jeffrey Richter这是[IOCP]实现高容量网络服务器的最佳方法。
[Windows Sockets2.0:Write Scalable Winsock Apps Using Completion Ports]Microsoft Corporation完成端口模型提供了最好的伸缩性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
矿产资源开发利用方案编写内容要求及审查大纲
矿产资源开发利用方案编写内容要求及《矿产资源开发利用方案》审查大纲一、概述
㈠矿区位置、隶属关系和企业性质。
如为改扩建矿山, 应说明矿山现状、
特点及存在的主要问题。
㈡编制依据
(1简述项目前期工作进展情况及与有关方面对项目的意向性协议情况。
(2 列出开发利用方案编制所依据的主要基础性资料的名称。
如经储量管理部门认定的矿区地质勘探报告、选矿试验报告、加工利用试验报告、工程地质初评资料、矿区水文资料和供水资料等。
对改、扩建矿山应有生产实际资料, 如矿山总平面现状图、矿床开拓系统图、采场现状图和主要采选设备清单等。
二、矿产品需求现状和预测
㈠该矿产在国内需求情况和市场供应情况
1、矿产品现状及加工利用趋向。
2、国内近、远期的需求量及主要销向预测。
㈡产品价格分析
1、国内矿产品价格现状。
2、矿产品价格稳定性及变化趋势。
三、矿产资源概况
㈠矿区总体概况
1、矿区总体规划情况。
2、矿区矿产资源概况。
3、该设计与矿区总体开发的关系。
㈡该设计项目的资源概况
1、矿床地质及构造特征。
2、矿床开采技术条件及水文地质条件。