Windows完成端口 IOCP模型(一)

1 Windows完成端口基本介绍

2他是只能在Windows下的基于SOCKET事件管理的模型

3与select不同,select需要多次重置管理句柄,IOCP只要一次

4有事件后select需要操作获取数据,而IOCP通知你的时候说明数据操作好了

5select管理句柄的数目有限,IOCP没有限制

6IOCP支持多线程同时等待。

我的设计思路一个线程用来侦听accept事件, 一个线程来侦听SOCKET的IO事件,

大部分框架都是这样, 其实可以只使用一个线程做异步SOCKET就完全足够了,现在

使用多线程来 就是看看这个IOCP的多线程用法,

在这之前先要了解下 异步通信 和 重叠I/O模型

异步通信机制: http://blog.51cto.com/blogger/draft/412685

重叠I/O模型: http://blog.51cto.com/12158490/2058180

我建议使用单线程 原因: 应为多个线程,拿到数据后,还是要发送到另外一个线程里面去,

然后做成事件队列, 也就是你线程拿到数据后, 还是要按队列线程,进行逻辑处理,多线程没意义。



2完成端口内部运行流程

完成端口的做法:事先开好几个线程,你有几个CPU我就开几个,首先是避免了线程的上下文切换,因为线程想要

执行的时候,总有CPU资源可用,然后让几个线程等着,等到有用户请求到来的时候,就把这些请求都加入到一个

公共消息队列中, 然后这几个开好的线程就排队逐一去从消息队列中取出消息并加以处理, 这种方式实现了

异步通信和负载均衡的问题,因为他提供了一种机制来使用几个线程"公平的"处理来自多个客户端的输入/输出

,并且线程如果没事干的时候,也会被系统挂起,不会占用CPU



3WSAAsyncSelect或者WSAEventSelect和完成端口

WSAAsyncSelect或者WSAEventSelect两种异步模型, 这两种模式一定没有使用overlapped(重叠)机制,

就不能算是真正的异步,可能是其内部维护了一个消息队列,这两个模式虽然实现了异步接收,却不能异步的发送,

完成端口他是先把用户数据接收回来后在通知用户直接来取,而这两种模式只会接到数据到达的通知,只能是由

应用程序自己去recv数据,性能上就发送了差异

要实现异步通信, 就要一个很强的I/O数据结构,叫重接结"Overtlapped",

Window所有异步通信都是基于他,完成端口也不例外

就是执行I/O请求的时间与线程执行其他任务的事件是重叠(overlapped)的,

重叠结构是异步通信机制实现的一个核心数据结构,因为几乎所有的网络操作例如发送/接收,都要用

WSASend()和WSARecv()代替,参数里面都会要附带一个重叠结构,因为重叠机构可以理解为是一个

网络操作的ID号,也就是说我们要利用重叠I/O提供的异步机制的话,每一个网络操作都要有一个唯一的ID号,

因为进来系统内核,一看到有重叠的I/O的调用进来了,就会使用其异步机制,并且操作系统就只能靠

这个重叠结构带有的ID号来区分是哪一个网络操作了,然后内核里处理完毕, 根据这个ID号,把对应的数据传上去.

4完成端口基本的使用流程 

完成端口也分步骤的

1调用CreateIoCompletionPort()函数创建一个完成端口,而且在一般情况下,我们需要并且只需要

建立一个完成端口,把他的句柄保存好, 之后只要使用这一个句柄就行了。

2根据和客户的I/O操作最好是自己建一个工作线程

3接入Socket连接, 有两种方式,1是和别的模型一样,有一个独立的线程,专门来accept客户端的连接,

二是用性能更好的异步AcceptEx()请求

4每当有客户端进来的时候,还是调用CreateIoCompletionPort()函数,这里不是建立完成端口,

而是把新连入的Socket句柄, 和你创建的完成端口绑定在一起。

5客户端连入后,我们要向这个客户端Socket提交一个请求,如接收文件要调用WSARecv()然后系统

就会去执行接收数据的操作, 就不用我们管了。

6 然后就要调用GetQueuedCompletionStatus()(是一个阻塞函数)里面是扫描端口的队列里是否有

网络通信的请求存在(例如读取数据,发送数据等),一旦有,就会将这个请求从完成端口的队列取回来,

继续执行本线程的后续代码,处理完毕后, 必须要再次 投递网络通信请求(WSARecv),如此循环。

5AcceptEx和Accept的区别

AcceptEx和Accept最大的区别,就是取消了阻塞方式的accept调用,也就是说AccentEx也是通过

完成端口来异步完成的。

这样做的好处就是:如果短时间内客户端并发连接请求不是很多,accept和AcceptEx在性能上区别不大,

虽然我们创建Socket只用一行SOCKET s =socket(...)一行代码,但是系统内部建立一个Socket是相当

耗费资源的,因为Winsock2是分层的机构体系,创建一个Socket需要用到多个Provider之间进行处理,

最终形成一个可用的套接字,总之,创建一个Socket的开心是相当高的。

AcceptEx比Accept强三点:

(1)最关键的是AcceptEx在客户端连入之前,就把客户端的Socket建立好了,也就是说,AcceptEx是先建立

Socket,然后发出的AcceptEx调用,也就是说,在进行客户端的通信之前,无论是否有客户端连入,

Socket都是提前建立好的,而不需要想accept是在客户端连入之后,在现场话费时间建立Socket,

(2)相比Accept只能阻塞方式建立一个连入的入口,对于大量的并发客户端来讲,是在是有点挤,

而AcceptEx可以在完成端口上投递多个请求,还有客户端连入的时候,就非常优雅而且从容.

(3)AcceptEx还有一个优点,就是投递AccepEx的时候,收取客户端发来的第一组数据,这是同时

进行的, 也就意味着,如果客户端只是连入但不发送数据的话,我们就不会收到这个AccepeEx完成的通知,

异步的AcceptEx使用起来比accept要麻烦。

由于时间关系,在下篇博客 会详细介绍完成端口的用法

实现图片中的功能

参考博客地址 http://www.cnblogs.com/lancidie/archive/2011/12/19/2293773.html



原文地址:http://blog.51cto.com/12158490/2058203

时间: 2024-08-28 06:13:59

Windows完成端口 IOCP模型(一)的相关文章

Windows完成端口 IOCP模型(二)

1详解完成端口基本使用 1创建完成端口 HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0); 参数其实就是-1,0,0,0. 最后一个参数代表的就是 NumberOfConcurrentThreads,就是允许应用同时执行的线程数量, 未来避免上下文切换,就是说让每个CPU只允许一个线程,设置为0 就是有多少处理器,就有多少工作线程. 原因就是如果一台机器有两个CPU(两核),如果让系统同时运行的 线程,多于本机

套接字I/O模型-完成端口IOCP

“完成端口”模型是迄今为止最为复杂的一种I/O模型.然而,假若一个应用程序同时需要管理为数众多的套接字,那么采用这种模型,往往可以达到最佳的系统性能!但不幸的是,该模型只适用于Windows NT和Windows 2000操作系统.因其设计的复杂性,只有在你的应用程序需要同时管理数百乃至上千个套接字的时候,而且希望随着系统内安装的CPU数量的增多,应用程序的性能也可以线性提升,才应考虑采用“完成端口”模型.要记住的一个基本准则是,假如要为Windows NT或Windows 2000开发高性能的

【windows核心编程】IO完成端口(IOCP)复制文件小例

1.演示内容 文件复制 2.提要 复制大文件时,使用FILE_FLAG_NO_BUFFERING标志 同时需要注意: 读写文件的偏移地址为 磁盘扇区 的整数倍 读写文件的字节数为 磁盘扇区 的整数倍 读文件到的缓冲区在进程地址空间中的地址为 磁盘扇区 的整数倍 3.JUST CODING #include "stdafx.h" #include <Windows.h> #include <process.h> #include <iostream>

【windows核心编程】IO完成端口(IOCP)复制文件小例前简单说明

1.关于IOCP IOCP即IO完成端口,是一种高伸缩高效率的异步IO方式,一个设备或文件与一个IO完成端口相关联,当文件或设备的异步IO操作完成的时候,去IO完成端口的[完成队列]取一项,根据完成键(Complete Key)来判断是哪个设备或文件的操作完成,然后再根据实际情况进行处理. 2.相关API 和 数据结构   将一个已完成的IO通知追加到IOCP的[完成队列]中 BOOL   PostQueuedCompletionStatus( HANDLE    hCompletionPort

IOCP模型总结(总结回顾)

IOCP旧代码重提,最近一直在玩其他方面的东东,时不时回顾一下,收益多多. IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型.它是应用程序使用线程池处理异步I/O请求的一种机制.在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求.这样就有很多的线程并行地运行在系统中.而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上.再加上创建新线程的开销比较大,所以造成了效率的

Window下高性能IOCP模型队列多线程下应用

IOCP,先从概念上认识一下.IOCP全称I/O Completion Port,中文译为I/O完成端口.是Windows平台最高效的I/O模块,现在IIS服务器,就采用IOCP模型.IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序.与使用select()或是其它异步方法不同的是,现在很多书,文字都直接将IOCP模块和网络编程关联起来,好像IOCP就是和网络打交道的.典型的IOCP模型的使用,是 将一个套接字(socket)与一个完成端口关联了起来,当一个网络事件发生的时

IOCP模型与网络编

一.前言:        在老师分配任务(“尝试利用IOCP模型写出服务端和客户端的代码”)给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装饰模式之类的那些呢?嘿嘿,不过好像是一个挺好玩的东西,挺好奇是什么东西来的,又是一个新知识啦~于是,开始去寻找一大堆的资料,为这个了解做准备,只是呢,有时还是想去找一本书去系统地学习一下,毕竟网络的资料还是有点零散.话说,本人学习这个模型的基础是,写过一个简单的Socket服务器及客户端程序,外加一个简单的Socke

IOCP模型与网络编程

IOCP模型与网络编程 一.前言:        在老师分配任务("尝试利用IOCP模型写出服务端和客户端的代码")给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装饰模式之类的那些呢?嘿嘿,不过好像是一个挺好玩的东西,挺好奇是什么东西来的,又是一个新知识啦~于是,开始去寻找一大堆的资料,为这个了解做准备,只是呢,有时还是想去找一本书去系统地学习一下,毕竟网络的资料还是有点零散.话说,本人学习这个模型的基础是,写过一个简单的Socket服务器及客

winsock编程IOCP模型实现代码

winsock编程IOCP模型实现代码 话不多说,上代码.借鉴<windows核心编程>部分源码和CSDN小猪部分代码. stdafx.h依赖头文件: 1 #include <iostream> 2 #include <WinSock2.h> 3 #include <MSWSock.h> 4 #include <vector> 5 #include "Singleton.h" 6 #include "IOCPWrap