IOCP完全解析

合集下载

名词解释IOCP简介四-Read

名词解释IOCP简介四-Read

hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
该语句的作用是返回一个句柄,在为完成端口分配了一个套接字句柄后,用来对那个 端口进行标定(引用)。
函数功能:注意该函数实际用于两个明显有别的目的: 1. 用于创建一个完成端口对象。 2. 将一个句柄同完成端口关联到一起。
IOCP简介

IOCP的开发
1、CreateIoCompletionPort
最开始创建一个完成端口时,唯一感兴趣的参数便是 NumberOfConcurrentThreads(并发线程的数量);前面三个参数都会被忽略。 NumberOfConcurrentThreads参数的特殊之处在于,它定义了在一个完成端口上, 同时允许执行的线程数量。理想情况下,我们希望每个处理器各自负责一个线程的运 行,为完成端口提供服务,避免过于频繁的线程“场景”切换。若将该参数设为0Байду номын сангаас 表明系统内安装了多少个处理器,便允许同时运行多少个线程!可用下述代码创建一 个I/O完成端口:
IOCP简介

IOCP的应用
可以看出完成端口是到目前为止最为复杂的输入输出模式。然而,当一个 应用不得不同时处理大量的socket时,它也提供了使系统性能达到最佳的可 能性。只有在被迫面对几百甚至几千个并发的socket、你又希望在添加CPU 后可以获得更好的scale时,才被派上战场。关于完成端口,最重要的是记住 这一点:如果你为winnt/2000开发处理大量socket I/O 请求的高性能服 务,它是你的最佳选择 IOCP不仅仅在通信socket上,同时也可以用于其他方面,例如读写文件, 比如把文件句柄关联到完成端口上,产生一定量的工作器线程,读取文件不同 的部分实际读取数据是系统内部处理,只是读取完了通知一下,并且把相关I O数据填充到结构体中

IOCP模型总结

IOCP模型总结

IOCP模型总结
IOCP模型的基本原理是使用操作系统提供的一个输入/输出完成端口,服务器在等待I/O完成时可以继续处理其他的请求(非阻塞),当操作系
统I/O操作完成之后,会通过回调函数的方式通知服务器,从而让服务器
能够及时处理已完成的请求。

2. 创建工作线程(CreateThread):服务器需要创建一定数量的工
作线程,用于处理来自客户端的请求和处理完成端口的通知。

这些工作线
程会在每一个请求到来时进行处理,当有I/O操作完成时,通过回调函数
的方式通知工作线程进行处理。

1.高吞吐量:通过多线程异步I/O的方式,充分利用了硬件性能和操
作系统的特性,能够处理大量的并发请求,提高服务器的吞吐量。

2.高性能:由于保持了非阻塞状态,减少了线程的阻塞时间,服务器
能够更快地响应请求,提供更好的性能。

3.可扩展性好:通过使用多线程模型,服务器可以根据需要动态调整
工作线程的数量,以适应不同的负载情况。

4.高并发处理能力:IOCP模型使用操作系统的通知机制,可以同时
处理多个I/O请求,大大提高了服务器的并发处理能力。

5.方便管理和维护:IOCP模型对服务器的管理和维护提供了便利,
通过将I/O完成的通知传递给操作系统,不需要服务器自己去维护和管理
线程,也无需关心线程的创建和销毁等问题。

总之,IOCP模型是一种高性能、高并发的I/O处理模式,通过利用
操作系统的特性和硬件性能,提高了服务器的处理能力。

它广泛应用于网
络服务器、数据库服务器等需要处理并发请求的场景,能够为用户提供更快速、更稳定的服务。

iocp 编程

iocp 编程

IOCP编程什么是IOCPIOCP(Input/Output Completion Ports)是一种高效的异步I/O模型,它在Windows操作系统中提供了对网络编程的支持。

通过使用IOCP,我们可以实现高性能、可伸缩性强的网络应用程序。

在传统的同步I/O模型中,当一个线程在等待数据时,它会被阻塞,直到数据到达。

而在异步I/O模型中,线程不会被阻塞,它可以继续执行其他任务。

IOCP就是基于这种异步I/O模型实现的。

IOCP的工作原理使用IOCP进行编程主要涉及以下几个核心概念:端口(Port)、完成包(Completion Packet)、套接字(Socket)和重叠操作(Overlapped Operation)。

•端口:一个端口代表一个I/O设备或者一个文件。

每个端口都有一个关联的完成端口。

•完成包:完成包是指一个I/O操作完成时所生成的信息块。

它包含了完成的状态、相关参数和返回值等信息。

•套接字:套接字是网络编程中用于进行通信的抽象概念。

•重叠操作:重叠操作是指一次I/O操作请求,在请求发出之后,线程就可以继续执行其他任务了。

IOCP主要通过以下几个步骤来实现异步I/O:1.创建一个完成端口(Completion Port)。

2.创建一个或多个工作者线程(Worker Thread),这些线程用于处理I/O操作。

3.将套接字关联到完成端口上,使得该套接字上的I/O操作能够被异步处理。

4.当有I/O操作完成时,系统会将相关的完成包放入完成队列中。

5.工作者线程从完成队列中获取完成包,并进行相应的处理。

IOCP的优势和适用场景相比于传统的同步阻塞模型,IOCP具有以下几个优势:1.高性能:IOCP能够充分利用CPU资源,提高程序的并发处理能力。

它通过异步I/O模型,使得线程在等待数据时不被阻塞,可以继续执行其他任务,从而充分利用了CPU资源。

2.可伸缩性:IOCP可以轻松地扩展到支持大量的并发连接。

完成端口详细解析

完成端口详细解析

关于完成端口(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模型的原理和工作过程IOCP模型的原理和工作过程如下:原理:IOCP模型的核心原理是利用操作系统提供的异步I/O和内核级事件通知机制。

异步I/O使得应用程序可以在等待I/O完成时继续处理其他任务,而内核级事件通知机制可以使得操作系统在I/O完成后主动通知应用程序。

通过将I/O操作的处理放在操作系统层面,IOCP模型能够实现高并发、高吞吐量的网络通信。

工作过程:1.创建IOCP对象:应用程序首先创建一个IOCP对象,用于和操作系统进行通信。

2.绑定套接字:应用程序将要进行异步I/O操作的套接字与IOCP对象进行关联。

3.接受连接:应用程序使用套接字进行监听,并且接受到客户端连接请求后,将连接套接字与IOCP对象进行关联,从而使得这个连接套接字能够参与IOCP模型的异步I/O操作。

4.发送和接收数据:应用程序通过调用操作系统提供的异步I/O操作函数,发起网络数据的发送和接收操作。

在发送和接收操作完成之前,应用程序可以继续处理其他任务。

5.等待通知:在发送和接收操作完成之后,应用程序会调用一个等待通知的函数,将自己挂起,等待操作系统的通知。

6.I/O完成通知:当操作系统中发生I/O操作完成的事件时,IOCP对象会通知应用程序,并将I/O操作的结果返回给应用程序。

7.处理完成的I/O操作:应用程序在收到I/O完成的通知后,可以根据返回的结果进行相应的处理。

通常会将I/O操作的结果放入一个队列中,以便后续的处理。

8.处理队列中的完成操作:应用程序会不断地从队列中取出已完成的I/O操作,并进行相应的处理。

处理完成的操作后,应用程序可以继续发起新的I/O操作,从而实现不断地进行网络通信。

总结:IOCP模型利用操作系统提供的异步I/O和内核级事件通知机制,将网络通信的I/O操作交给操作系统来处理,从而实现了高并发、高吞吐量的网络通信。

应用程序通过调用操作系统提供的异步I/O函数来发起发送和接收数据的操作,在操作完成前可以继续处理其他任务。

IOCP

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 都完成了,那么就在完成端口那里排成一个队列)。

iocp_2_重叠异步IO

iocp_2_重叠异步IO

IOCP(完成端口)是什么以下就是IOCP的模型图,能看懂么?IOCP模型(图1.1)IOCP是什么IOCP模型相对于其它模型(select,。

),确实有点复杂。

它虽然就那么几个I/O操作函数,但它们都有一大串的参数,返回值的多样性,大大的加大了理解难度。

但是如果你理解了它,掌握了难点重点,也就那么一回事。

可以从以下几方理解什么是IOCP。

一、IOCP的实现步骤。

二、IOCP的核心--重叠异步I/O。

三、如何提交I/O请求。

四、如何取得I/O返回的操作结果,并作处理。

五、IOCP的一个完整例子。

< 二>重叠异步I/O重叠异步I/O要点:1.驱动原理2.VOERLAPPED 结构的作用3.OVERLAPPED 结构的扩展和应用1.重叠异步I/O的驱动原理IOCP的核心就是重叠异步I/O。

首先理解它的工作原理,什么是重叠异步I/O呢?重叠异步I/O的原理是:客户(应用程序)向I/O管理器提交I/O操作(读或写数据)请求,然后去忙其它事。

I/O操作完成之后,I/O管理器再通知客户。

同样,IOCP就是socket向I/O管理器提交各种请求,然后等待并取得I/O管理器返回的结果,如图1.1 所示。

IOCP就像你去银行办理业务,先去取个号码,然后等待叫号。

在拿到号码到被叫号期间,你可以干什么都行(IOCP和叫号还是有点区别的,就是IOCP会保留结果直到被取走,而叫号在叫到你的号码时,你不在,那么你的号码就作废了)。

也可以这么理解重叠异步I/O,就是在一头提交I/O请求(可以一次或多次—叫重叠),然后再另一头取得I/O操作的结果。

这两个操作是不同时、不连续的,这就是异步的原因。

2.VOERLAPPED 结构的作用提交I/O请求的socket函数有:ConnectEx、AcceptEx、WSASend、WSARecv。

取得I/O操作返回结果的函数有:GetQueuedCompletionStatus,GetOverlappedResult 等。

IOCP完成端口详解(10年吐血大总结)

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"的缺点的,它充分利用内核对象的调度,只使用少量的几个线程来处理和客户端的所有通信,消除了无谓的线程上下文切换,最大限度的提高了网络通信的性能,这种神奇的效果具体是如何实现的请看下文。

简述iocp模型的原理和工作过程

简述iocp模型的原理和工作过程

简述iocp模型的原理和工作过程IOCP(Input/Output Completion Port)模型是一种高效的异步IO 机制,它可以帮助我们更好地处理并发IO请求。

在本文中,我们将详细介绍IOCP模型的原理和工作过程。

一、IOCP模型的基本原理1.1 异步IO在传统的同步IO模型中,当程序调用一个IO操作时,它必须等待该操作完成后才能继续执行后面的代码。

这种方式会导致程序在等待IO 操作完成时出现阻塞,从而浪费了CPU资源。

相比之下,异步IO模型允许程序调用一个IO操作后立即返回,并在后台处理该操作。

当该操作完成时,系统将通知程序,并返回结果。

这种方式可以提高程序的并发性和吞吐量。

1.2 IOCP机制为了更好地支持异步IO,Windows引入了IOCP机制。

它是一种通知机制,可以帮助我们更好地处理异步IO请求。

具体来说,当一个异步IO请求被提交到系统中时,系统会为其分配一个I/O Completion Port(即完成端口)。

当该请求完成时,系统将通知该端口,并返回相关信息。

程序可以通过监听该端口来获取请求完成的通知,并进行相应的处理。

二、 IOCP模型的工作过程2.1 创建I/O Completion Port首先需要创建I/O Completion Port(以下简称IOCP)。

可以通过CreateIoCompletionPort函数来创建一个IOCP。

该函数返回一个句柄,该句柄用于后续的操作。

2.2 将Socket与IOCP关联接下来需要将Socket与IOCP关联。

可以通过CreateIoCompletionPort或者WSAEventSelect函数来实现。

2.3 提交异步IO请求当需要进行异步IO操作时,可以使用WSASend、WSARecv等函数来提交异步IO请求。

这些函数会将请求提交到系统中,并立即返回。

2.4 处理完成通知当一个异步IO请求完成时,系统会向其关联的IOCP发送一个完成通知。

深入解析IOCP

深入解析IOCP

1.介绍1.1高并发服务器(1)要求大规模的连接/会话可能同时进行(2)列子:Web服务器, 邮件服务器1.2线程池架构(1)每个连接分配一个线程,将导致过多的线程。

(2)线程消耗内存,比如堆栈等等。

(3)操作系统创建和关闭线程,都将花费很多的时间在线程之间的切换2.线程模型2.1基于会话模型(1)每个线程服务于一个客户端,比如HTTP会话。

(2)线程被用于状态跟踪和CPU调度。

(3)活跃线程的数量等于并发客户端会话的数量2.2基于I/O模型(1)将状态跟踪从CPU调度中分离出来。

(2)线程是所有同质,仅为I/O调用保持状态。

(3)一个线程可以服务于不同的会话,在不同的时刻。

(4)一个会话可以被服务,通过不同的线程,在不同的时刻。

(5)因此,从一个线程不是专门对于一个会话,仅仅专门对于一个I/O请求处理。

3.基于I/O的线程调度3.1并发限制(1)线程是和CPU绑定最大活跃线程的个数== CPU个数(2)线程是和I/O绑定最大的工作线程个数>= I/O并行个数(3)根据实验/基准设置3.2线程池大小(1)线程是和CPU绑定等于并发限制数(2)线程是和I/O绑定最大的工作线程个数>= I/O并行个数(3)根据实验/基准设置3.3查询系统信息typedef struct _SYSTEM_INFO {union {DWORD dwOemId;struct {WORD wProcessorArchitecture;WORD wReserved;};};DWORD dwPageSize;LPVOID lpMinimumApplicationAddress;LPVOID lpMaximumApplicationAddress;DWORD_PTR dwActiveProcessorMask;DWORD dwNumberOfProcessors;DWORD dwProcessorType;DWORD dwAllocationGranularity;WORD wProcessorLevel;WORD wProcessorRevision;} SYSTEM_INFO;4.Win32 完成端口4.1什么是IOCP是一个Win32 机制,方便于带有控制并发的服务器的并发执行。

IOCP_原理_代码

IOCP_原理_代码

Windows I/O完成端口WINDOWS完成端口编程1、基本概念2、WINDOWS完成端口的特点3、完成端口(Completion Ports )相关数据结构和创建4、完成端口线程的工作原理5、Windows完成端口的实例代码WINDOWS完成端口编程摘要:开发网络程序从来都不是一件容易的事情,尽管只需要遵守很少的一些规则:创建socket,发起连接,接受连接,发送和接收数据,等等。

真正的困难在于:让你的程序可以适应从单单一个连接到几千个连接乃至于上万个连接。

利用Windows完成端口进行重叠I/O的技术,可以很方便地在Windows平台上开发出支持大量连接的网络服务程序。

本文介绍在Windows平台上使用完成端口模型开发的基本原理,同时给出实际的例子。

本文主要关注C/S结构的服务器端程序,因为一般来说,开发一个大容量、具有可扩展性的winsock程序就是指服务程序。

1、基本概念设备---指windows操作系统上允许通信的任何东西,比如文件、目录、串行口、并行口、邮件槽、命名管道、无名管道、套接字、控制台、逻辑磁盘、物理磁盘等。

绝大多数与设备打交道的函数都是CreateFile/ReadFile/WriteFile 等,所以我们不能看到**File函数就只想到文件设备。

与设备通信有两种方式,同步方式和异步方式:同步方式下,当调用ReadFile这类函数时,函数会等待系统执行完所要求的工作,然后才返回;异步方式下,ReadFile这类函数会直接返回,系统自己去完成对设备的操作,然后以某种方式通知完成操作。

重叠I/O----顾名思义,就是当你调用了某个函数(比如ReadFile)就立刻返回接着做自己的其他动作的时候,系统同时也在对I/0设备进行你所请求的操作,在这段时间内你的程序和系统的内部动作是重叠的,因此有更好的性能。

所以,重叠I/O是在异步方式下使用I/O设备的。

重叠I/O需要使用的一个非常重要的数据结构:OVERLAPPED。

IOCP详解

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,这个时间段中⽤户线程⼀直处于等待状态,如果这个时间段⽐较短,则不会有什么问题,但是如果时间⽐较长,那么这段时间线程会⼀直处于挂起状态,这就会很严重影响效率,所以我们可以考虑在这段时间做些事情。

IOCP的学习总结

IOCP的学习总结

IOCP的学习总结IOCP(I/O Completion Port),常称I/O完成端口。

IOCP模型属于一种通讯模型,适用于(能控制并发执行的)高负载服务器的一个技术。

通俗一点说,就是用于高效处理很多很多的客户端进行数据交换的一个模型。

或者可以说,就是能异步I/O操作的模型。

1、基本概念IOCP全称I/O Completion Port,中文译为I/O完成端口。

IOCP是一个异步I/O 的API,它可以高效地将I/O事件通知给应用程序。

与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。

然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。

然后应用程序可以对核心层进行查询以得到此完成端口。

2、IOCP模型的优缺点优点:①帮助维持重复使用的内存池。

(与重叠I/O技术有关)②去除删除线程创建/终结负担。

③利于管理,分配线程,控制并发,最小化的线程上下文切换。

④优化线程调度,提高CPU和内存缓冲的命中率。

缺点:理解以及编码的复杂度较高。

对使用者有一定要求。

需了解以下基本知识:①同步与异步②阻塞与非阻塞③重叠I/O技术④多线程⑤栈、队列这两种基本的数据结构3、相关API①与SOCKET相关1、链接套接字动态链接库:int WSAStartup(...);2、创建套接字库:SOCKET socket(...);3、绑字套接字:int bind(...);4、套接字设为监听状态:int listen(...);5、接收套接字:SOCKET accept(...);6、向指定套接字发送信息:int send(...);7、从指定套接字接收信息:int recv(...);[1]②与线程相关1、创建线程:HANDLE CreateThread(...);③重叠I/O技术相关1、向套接字发送数据:int WSASend(...);2、向套接字发送数据包:int WSASendTo(...);3、从套接字接收数据:int WSARecv(...);4、从套接字接收数据包:int WSARecvFrom(...);④IOCP相关1、创建/关联完成端口:HANDLE WINAPI CreateIoCompletionPort(...);2、获取队列完成状态: BOOL WINAPI GetQueuedCompletionStatus(...);3、投递一个队列完成状态:BOOL WINAPI PostQueuedCompletionStatus(...);4、详细概念这里我要对上面的一些概念略作补充,在解释[完成]两字之前,我想先简单的提一下同步和异步这两个概念,逻辑上来讲做完一件事后再去做另一件事就是同步,而同时一起做两件或两件以上事的话就是异步了。

IOCP——精选推荐

IOCP——精选推荐

IO Completion Port, Windows上提供的最有效实现高性能server的方式(无论是file server, web server还是别的任何类似大量并发io请求的server),IIS本身就是基于此的。

可惜,到目前为止没有一个真正简单的示例。

今日便让我打响这第一炮吧。

没有一个简明例程的根源,可以说是因为IoCompletionPort本身的API设计非常糟糕,一个CreateIoCompletionPort包含了太多功能,名称又很confusing,让人云里雾里。

所有的的例程,为了便于理解,都把这些让人迷惑的API封装,构造自己的class,但是呢,这样虽然从软件设计角度来说清晰了,但是对于了解IoCompletionPort的使用来说,反而更迷惑了(因为调用被分散到各个class中)。

本文的目的是用最简明的例子来介绍如何使用IO Completion Port。

在此之前,先要说IO Completion Port到底是什么东西-----就是threads pool,一个由Windows自动管理的threads pool. 好,你就需要了解这么多,再说多了就违背了本文的宗旨---提供简明例程。

1. IO Completion Port的程序,大致上可以划分为以下步骤:2. CreateIOCompletionPort (可以理解为初始化threads pool)3. 建立threads (就是一般的CreateThread或者_beginthreadex,将第一步所得到的HANDLE作为参数传进去,这个跟一般的thread没任何差别)4. 开始IO 操作,比如建立SOCKET, bind...5. 在第一个Async IO之前,将上一步建立的HANDLE(比如socket)绑定到第一步得到的IO Completion Port的HANDLE 上6. 根据具体情况操作IO好吧,还是用代码来看比较直接:先来看主程序:view plainc opy to clipboardprint?1.int _tmain(int argc, _TCHAR* argv[])2.{3.4.// argv[1]为ip, argv[2]为port5.// CTcpServer只是一个对socket的简单封装,代码6.// 后面给出7. CTcpServer server(argv[1], argv[2]);8.if (!server.StartListening())9. {10. printf("failed listening\n");11.return 1;12. }13.14.// initialize IoCompletionPort15. SOCKET& listeningSocket = server.Socket();16.//1. 初始化IO Completion Port17.HANDLE hIocp = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);18.19.if(hIocp == NULL)20. {21. printf("cannot create io completion port\n");22.return 1;23. }24.25.//2. 绑定socket到completion port26.//这意思是说,后面所有在这个socket上的async27.// io 操作,都会notify这个completion port的28.//threads29.if (0 == ::CreateIoCompletionPort((HANDLE)listeningSocket, hIocp,(ULONG_PTR)0, 0))30. {31. printf("cannot associate listening socket to io completion port\n");32.return 1;33. }34.35.//3. 创建threads,将io completion port36.// HANDLE 作为参数传入,这样每个thread37.// 都能在有IO请求时query其status,参见38.// thread的具体代码39.int threadPoolSize = 4;40.41.HANDLE hWorker;42.43.for(int i=0;i<threadPoolSize; ++i)44. {45. hWorker = CreateThread(NULL, 0, WorkerThreadFunc, (LPVOID)hIocp, 0, NULL);46. CloseHandle(hWorker);47. }48.49.//4. 等待新连接,因为我们不要busy loop, 所以50.// 每个TCP连接需要等待并检查51.// FD_ACCEPT event,然后用AcceptEx52.while(true)53. {54. printf("waiting for connection\n");55.if (server.WaitForAcceptEvent(10000))56. {57.// 只管Accept了,至于Recv/Send由上面建立的58.// thread来负责,后面会说thread的功能59.server.AcceptNewConnection();60. }61. }62.63.return 1;64.}然后先来看thread的实现. IO Completion Port的thread因为是放入一个thread pool 中,所以每个thread是“通用”的,换句话说,每个thread要能够完成多种功能,用伪代码来说是这样:Wait For IO Notification; ---> 等待比如Socket上的一个event,至于是什么event 先不管。

IOCP完成端口详解

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编程之基本原理

IOCP编程之基本原理在我的博客之前写了很多关于IOCP的“行云流水”似的看了让人发狂的文章,尤其是几篇关于IOCP加线程池文章,更是让一些功力不够深厚的初学IOCP者,有种吐血的感觉。

为了让大家能够立刻提升内力修为,并且迅速的掌握IOCP这个Windows平台上的乾坤大挪移心法,这次我决定给大家好好补补这个基础。

要想彻底征服IOCP,并应用好IOCP这个模型,首先就让我们穿越到遥远的计算机青铜器时代(以出现PC为标志),那时候普通的PC安装的还是DOS平台,微软公司主要靠这个操作系统在IT界的原始丛林中打拼,在DOS中编写程序,不得不与很多的硬件直接打交道,而最常操作的硬件无非是键盘、声显卡、硬盘等等,这些设备都有一个特点就是速度慢,当然是相对于PC平台核心CPU的速度而言,尤其是硬盘这个机械电子设备,其速度对于完全电子化得CPU来说简直是“相对静止”的设备。

很多时候CPU可以干完n件(n>1000)事情的时间中,这些硬件可能还没有完成一件事情,显然让CPU和这些硬件同步工作将是一种严重的浪费,并且也不太可能,此时,聪明的硬件设计师们发明了一种叫做中断的操作方式,用以匹配这种速度上的严重差异。

中断工作的基本原理就是,CPU首先设置一个类似回调函数的入口地址,其次CPU对某个硬件发出一个指令,此时CPU 就去干别的活计了,最后那个慢的象蜗牛一样的硬件执行完那个指令后,就通知CPU,让CPU暂时“中断”手头的工作,去调用那个“回调函数”。

至此一个完整的中断调用就结束了。

这个模型曾经解决了显卡与CPU不同步的问题,最重要的是解决了硬盘速度与CPU速度严重不匹配的问题,并因此还派生出了更有名的DMA(直接内存访问技术,主要是指慢速硬件可以读写原本只能由CPU直接读写的内存)硬盘IO方式。

(注意这里说的中断工作方式只是中断工作方式的一种,并不是全部,详细的中断原理请参阅其它专业文献。

)其实“中断”方式更像是一种管理模型,比如在一个公司中,如果要老板时时刻刻盯着员工作事情,那么除非是超人,否则无人能够胜任,同时对于老板这个稀缺资源来说也是一种极起严重的浪费。

[转]IOCP介绍

[转]IOCP介绍

[转]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,线程就会将会与某个指定的完成端⼝建⽴联系,⼀直延续其该线程的存在周期,或被指定了不同的完成端⼝,或者释放了与完成端⼝的联系。

⼀个线程只能与最多不超过⼀个的完成端⼝发⽣联系。

IOCP浅析1

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,这样用户就可以不必等待,效率就会非常高。

iocp 编程 -回复

iocp 编程 -回复

iocp 编程-回复IOCP(Input/Output Completion Ports)编程是一种高效的服务器端编程模型,它利用操作系统级的异步I/O机制,能够实现高性能、高可扩展性和高并发的网络应用程序。

本文将逐步解释IOCP编程,包括其原理、特点、实现方式以及常见应用场景。

一、IOCP编程的原理IOCP编程基于操作系统提供的异步I/O机制,通过操作系统内核中的完成端口(completion port)来实现异步I/O操作的管理和处理。

操作系统将I/O请求和完成事件的管理和调度交给了完成端口,应用程序通过与完成端口进行通信来管理和处理I/O操作。

当应用程序需要进行I/O操作时,它可以向完成端口提交一个I/O请求。

完成端口会将这个请求发送给操作系统的驱动程序,并立即返回给应用程序,不会阻塞应用程序的继续执行。

当I/O操作完成时,操作系统会将完成事件通知完成端口,完成端口再将完成事件通知给应用程序进行处理。

应用程序可以通过从完成端口获取完成事件来获取已完成的I/O操作的结果,而无需进行轮询等待。

通过这种方式,IOCP编程能够高效地处理大量的并发I/O操作,提高服务器性能和可扩展性。

二、IOCP编程的特点1. 高性能:IOCP编程利用了操作系统提供的异步I/O机制,能够实现高效率的I/O操作处理。

相对于传统的同步I/O模型,它能够极大地提升服务器的性能。

2. 高可扩展性:IOCP编程通过使用完成端口进行异步I/O操作的管理和处理,能够很好地适应大量并发连接的场景。

它能够实现更高的并发能力和更低的系统资源开销,使得服务器能够轻松应对高并发请求。

3. 简化了编程模型:相对于传统的多线程或多进程方式处理并发I/O操作的编程模型,IOCP编程可以减少线程和进程的创建和维护的开销,简化了编程模型。

应用程序只需要关注I/O操作提交和完成事件的处理,而不需要关心具体的线程或进程创建和管理。

三、IOCP编程的实现方式IOCP编程可以在不同的操作系统平台上实现,如Windows和Linux。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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,
#pragma comment(lib,"ws2_32.lib") 从本质上说,完成端口模型要求创建一个 windows 完成端口对象,该对象通过指定数量的线程,对重叠 I/O 请求进 行管理,以便为已经完成的重叠 I/O 请求提供服务。 首先要创建一个 I/O 完成端口对象,用它面向任意数量的套接字句柄,管理多个 I/O 请求。调用以下函数创建 完成端口对象: HANDLE CreateIoCompletionPort( HANDLE FileHandle,// 同 IOCP 关联在一起的套接字句柄 HANDLE ExistingCompletionPort,// IOCP 句柄 ULONG_PTR CompletionKey, // 完成健 DWORD NumberOfConcurrentThreads // 在 IOCP 上,同时允许执行的线程数量 ); 该函数有两个作用: (1)创建一个完成端口对象 (2)将一个句柄同完成端口关联到一起 然后就要创建一定数量的工作者线程,以便在套接字的 I/O 请求投递给完成端口后,为完成端口提供服务。写 文字描述很烦,还是看代码吧: // NetServer3.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "NetServer3.h" #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") #include <iostream> using namespace std; /**/////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /**/////////////////////////////////////////////////////////////////////////// // 单句柄数据 typedef struct tagPER_HANDLE__family = PF_INET; InternetAddr.sin_port = htons(5000); InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(Listen, (SOCKADDR*)&InternetAddr, sizeof(InternetAddr)); listen(Listen, 5); BOOL b = TRUE; while (b) { PER_HANDLE_DATA * PerHandleData = NULL; SOCKADDR_IN saRemote; SOCKET Accept; int RemoteLen; // 5.接收连接,并分配完成端口,这儿可以用 AcceptEx 来代替,以创 // 建可伸缩的 Winsock 应用程序。 RemoteLen = sizeof(saRemote); Accept = accept(Listen, (SOCKADDR*)&saRemote, &RemoteLen); // 6.创建用来和套接字关联的单句柄数据信息结构 PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)); cout << "Socket number " << Accept << " connected" << endl; PerHandleData->Socket = Accept; memcpy(&PerHandleData->ClientAddr, &saRemote, RemoteLen); // 7.将接受套接字和完成端口关联起来 CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD)PerHandleData, 0); // 开始在接受套接字上处理 I/O // 使用重叠 I/O 机制,在新建的套接字上投递一个或多个异步 // WSARecv 或 WSASend 请求。这些 I/O 请求完成后,工作者线程 // 会为 I/O 请求提供服务,之后就可以坐享其成了 static int const DATA_BUFSIZE = 4096; // DWORD RecvBytes = 0;
{ SOCKET Socket; SOCKADDR_STORAGE ClientAddr; // 将和这个句柄关联的其他有用信息,尽管放在这里面吧 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA; // 但 I/O 操作数据 typedef struct tagPER_IO_DATA { OVERLAPPED Overlapped; WSABUF DataBuf; char buffer[1024]; int BufferLen; int OperationType; // 可以作为读写的标志,为简单,我忽略了 }PER_IO_DATA, *LPPER_IO_DATA; DWORD WINAPI ServerWorkerThread(LPVOID lpParam); /**////////////////////////////////////////////////////////////////////////////// // The one and only application object CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; // initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs cerr << _T("Fatal Error: MFC initialization failed") << endl; nRetCode = 1; } else { // TODO: code your application's behavior here. CString strHello; strHello.LoadString(IDS_HELLO); cout << (LPCTSTR)strHello << endl; }
/**/////////////////////////////////////////////////////////////////////////// HANDLE CompletionPort; WSADATA wsd; SYSTEM_INFO SystemInfo; SOCKADDR_IN InternetAddr; SOCKET Listen; // 加载 WinSock2.2 WSAStartup(MAKEWORD(2, 2), &wsd); // 1.创建一个 I/O 完成端口 CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // 2.确定系统中有多少个处理器 GetSystemInfo(&SystemInfo); // 3.基于系统中可用的处理器数量创建工作器线程 for (int i = 0; i < SystemInfo.dwNumberOfProcessors * 2; ++i) { HANDLE ThreadHandle; // 创建一个服务器的工作器线程,并将完成端口传递到该线程 ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, NULL); CloseHandle(ThreadHandle); } // 4.创建一个监听套接字,以下的套路都是固定的。 Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
相关文档
最新文档