首页 /编程语言和算法/其它语言
 IOCP(I/O Completion Port),常称I/O完成端口
2024年4月6日 19:38

IOCP全称I/O Completion Port,中文译为I/O完成端口。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。

IOCP模型的优缺点

优点:

① 帮助维持重复使用的内存池。(与重叠I/O技术有关)

② 去除删除线程创建/终结负担。

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

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

缺点:

理解以及编码的复杂度较高。对使用者有一定要求。

需了解以下基本知识:

① 同步与异步

② 阻塞与非阻塞

③ 重叠I/O技术

④ 多线程

⑤ 栈、队列这两种基本的数据结构

相关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(...);

详细概念

这里我要对上面的一些概念略作补充,在解释[完成]两字之前,我想先简单的提一下同步和异步这两个概念,逻辑上来讲做完一件事后再去做另一件事就是同步,而同时一起做两件或两件以上事的话就是异步了。你也可以拿单线程和多线程来作比喻。但是我们一定要将同步和堵塞,异步和非堵塞区分开来,所谓的堵塞函数诸如accept(…),当调用此函数后,此时线程将挂起,直到操作系统来通知它,"HEY兄弟,有人连进来了",那个挂起的线程将继续进行工作,也就符合"生产者-消费者"模型。堵塞和同步看上去有两分相似,但却是完全不同的概念。大家都知道I/O设备是个相对慢速的设备,不论打印机,调制解调器,甚至硬盘,与CPU相比都是奇慢无比的,坐下来等I/O的完成是一件不甚明智的事情,有时候数据的流动率非常惊人,把数据从你的文件服务器中以Ethernet速度搬走,其速度可能高达每秒一百万字节,如果你尝试从文件服务器中读取100KB,在用户的眼光来看几乎是瞬间完成,但是,要知道,你的线程执行这个命令,已经浪费了10个一百万次CPU周期。所以说,我们一般使用另一个线程来进行I/O。重叠IO[overlapped I/O]是Win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这也就是[完成]的含义。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内部正是以线程来完成overlapped I/O。你可以获得线程所有利益,而不需要付出什么痛苦的代价。

完成端口中所谓的[端口]并不是我们在TCP/IP中所提到的端口,可以说是完全没有关系。IOCP只不过是用来进行读写操作,和文件I/O倒是有些类似。既然是一个读写设备,我们所能要求它的只是在处理读与写上的高效。

下面是一个VC++实现IOCP服务器框架的流程:[1]

当然,IOCP也是基于Winsock2套接字库的,所以在开始先必须初始化套接字库。

IOCP除了需一个服务器套接字外,还需一个完成端口的句柄,该句柄直接调用API

之后为套接字绑定一个本地端口,用来监听客户端的连接

绑定端口之后,建立一个监听线程,用来监听客户端的连接,当有连接进来时,将该连接的套接字加入到IOCP对队列中,同时再创建几个工作线程,这样在该连接发生请求时,IOCP模型就会在工作线程通知,这样我们就可以在工作线程中,完成对客户端的请求做出一系列响应。

工作线程中循环调用了 GetQueuedCompletionStatus 这个API来取出当前活动的套接字,当套接字有数据应请求或者断开时。该函数也会立即返回。

如果要对工作线程停止,PostQueuedCompletionStatus 使用该API 向工作发送停止命令,工作线程收到此命令后,可以安全退出线程。

以上就是大致实现流程,仅限于VC++开发使用,由于其它平台语言实现起来有些困难,可以采用一些第三方做的 IOCP支持库,如网上现比较好用的有易语言和C++版的,IOCP服务器模型支持库,该第三方库写的比较好用。可以直接使用的。还有一些其它版本的。实现原理也是以上方法。

 
全部回复(0)
首页 | 电脑版 |