`

理解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
完成端口模型提供了最好的伸缩性。这个模型非常适用来处理数百乃至上千个套接字。
[Windows网络编程2nd] Anthony Jones & Jim Ohlund
I/O completion ports特别显得重要,因为它们是唯一适用于高负载服务器[必须同时维护许多连接线路]的一个技术。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,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方 法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端 口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。

  这里我要对上面的一些概念略作补充,在解释[完成]两字之前,我想先简单的提一下同步和异步这两个概念,逻辑上来讲做完一件事后再去做另一件事就是同 步,而同时一起做两件或两件以上事的话就是异步了。你也可以拿单线程和多线程来作比喻。但是我们一定要将同步和堵塞,异步和非堵塞区分开来,所谓的堵塞函 数诸如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中所提到的端口,可以说是完全没有关系。我到现在也没想通一个I/O设备[I/O Device]和端口[IOCP中的Port]有什么关系。估计这个端口也迷惑了不少人。IOCP只不过是用来进行读写操作,和文件I/O倒是有些类似。 既然是一个读写设备,我们所能要求它的只是在处理读与写上的高效。在文章的第三部分你会轻而易举的发现IOCP设计的真正用意。


IOCP和网络又有什么关系?

int main()
{
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    ListeningSocket = socket(AF_INET, SOCK_STREAM, 0);
    bind(ListeningSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));
    listen(ListeningSocket, 5);
    int nlistenAddrLen = sizeof(ClientAddr);
    while(TRUE)
    {
        NewConnection = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &nlistenAddrLen);
        HANDLE hThread = CreateThread(NULL, 0, ThreadFunc, (void*) NewConnection, 0, &dwTreadId);
        CloseHandle(hThread);
    }
    return 0;
}
 


  相信只要写过网络的朋友,应该对这样的结构在熟悉不过了。accept后线程被挂起,等待一个客户发出请求,而后创建新线程来处理请求。当新线程处理 客户请求时,起初的线程循环回去等待另一个客户请求。处理客户请求的线程处理完毕后终结。

  在上述的并发模型中,对每个客户请求都创建了一个线程。其优点在于等待请求的线程只需做很少的工作。大多数时间中,该线程在休眠[因为recv处于堵 塞状态]。

  但是当并发模型应用在服务器端[基于Windows NT],Windows NT小组注意到这些应用程序的性能没有预料的那么高。特别的,处理很多同时的客户请求意味着很多线程并发地运行在系统中。因为所有这些线程都是可运行的 [没有被挂起和等待发生什么事],Microsoft意识到NT内核花费了太多的时间来转换运行线程的上下文[Context],线程就没有得到很多 CPU时间来做它们的工作。

  大家可能也都感觉到并行模型的瓶颈在于它为每一个客户请求都创建了一个新线程。创建线程比起创建进程开销要小,但也远不是没有开销的。

  我们不妨设想一下:如果事先开好N个线程,让它们在那hold[堵塞],然后可以将所有用户的请求都投递到一个消息队列中去。然后那N个线程逐一从消 息队列中去取出消息并加以处理。就可以避免针对每一个用户请求都开线程。不仅减少了线程的资源,也提高了线程的利用率。理论上很不错,你想我等泛泛之辈都 能想出来的问题,Microsoft又怎会没有考虑到呢?!

  这个问题的解决方法就是一个称为I/O完成端口的内核对象,他首次在Windows NT3.5中被引入。

  其实我们上面的构想应该就差不多是IOCP的设计机理。其实说穿了IOCP不就是一个消息队列嘛!你说这和[端口]这两字有何联系。我的理解就是 IOCP最多是应用程序和操作系统沟通的一个接口罢了。

  至于IOCP的具体设计那我也很难说得上来,毕竟我没看过实现的代码,但你完全可以进行模拟,只不过性能可能…,如果想深入理解IOCP, Jeffrey Ritchter的Advanced Windows 3rd其中第13章和第14张有很多宝贵的内容,你可以拿来窥视一下系统是如何完成这一切的。


实现方法

Microsoft为IOCP提供了相应的API函数,主要的就两个,我们逐一的来看一下:


HANDLE CreateIoCompletionPort (
    HANDLE FileHandle,              // handle to file
    HANDLE ExistingCompletionPort,  // handle to I/O completion port
    ULONG_PTR CompletionKey,        // completion key
    DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
);
 


在讨论各参数之前,首先要注意该函数实际用于两个截然不同的目的:
1.用于创建一个完成端口对象
2.将一个句柄[HANDLE]和完成端口关联到一起

  在创建一个完成一个端口的时候,我们只需要填写一下NumberOfConcurrentThreads这个参数就可以了。它告诉系统一个完成端口上 同时允许运行的线程最大数。在默认情况下,所开线程数和CPU数量相同,但经验给我们一个公式:
  线程数 = CPU数 * 2 + 2
要使完成端口有用,你必须把它同一个或多个设备相关联。这也是调用CreateIoCompletionPort完成的。你要向该函数传递一个已有的完成 端口的句柄,我们既然要处理网络事件,那也就是将客户的socket作为HANDLE传进去。和一个完成键[对你有意义的一个32位值,也就是一个指针, 操作系统并不关心你传什么]。每当你向端口关联一个设备时,系统向该完成端口的设备列表中加入一条信息纪录。

另一个API就是


BOOL GetQueuedCompletionStatus(
    HANDLE CompletionPort,        // handle to completion port
    LPDWORD lpNumberOfBytes,       // bytes transferred
    PULONG_PTR lpCompletionKey,   // file completion key
    LPOVERLAPPED *lpOverlapped,   // buffer
    DWORD dwMilliseconds         // optional timeout value
);

 


第一个参数指出了线程要监视哪一个完成端口。很多服务应用程序只是使用一个I/O完成端口,所有的I/O请求完成以后的通知都将发给该端口。简单的 说,GetQueuedCompletionStatus使调用线程挂起,直到指定的端口的I/O完成队列中出现了一项或直到超时。同I/O完成端口相关 联的第3个数据结构是使线程得到完成I/O项中的信息:传输的字节数,完成键和OVERLAPPED结构的地址。该信息是通过传递给 GetQueuedCompletionSatatus的 lpdwNumberOfBytesTransferred,lpdwCompletionKey和lpOverlapped参数返回给线程的。

根据到目前为止已经讲到的东西,首先来构建一个frame。下面为您说明了如何使用完成端口来开发一个echo服务器。大致如下:
  1.初始化Winsock
  2.创建一个完成端口
  3.根据服务器线程数创建一定量的线程数
  4.准备好一个socket进行bind然后listen
  5.进入循环accept等待客户请求
  6.创建一个数据结构容纳socket和其他相关信息
  7.将连进来的socket同完成端口相关联
  8.投递一个准备接受的请求
以后就不断的重复5至8的过程
那好,我们用具体的代码来展示一下细节的操作。


Quote : http://dev.gameres.com/Program/Control/IOCP.htm

分享到:
评论

相关推荐

    Socket I/O 模型的使用示例

    在本文中,我们将深入探讨异步Socket I/O模型的几种常见实现方式,包括选择(select)、异步选择(asynchronous select)、事件选择(poll)、重叠I/O(overlapped I/O)以及完成端口(completion ports)。...

    Windows Socket五种I/O模型——代码全攻略

    #### 六、完成端口(Completion Port)I/O模型 完成端口I/O模型是Windows平台下最高性能的I/O模型,尤其适合处理大量的并发连接。它利用了操作系统内核的支持,可以高效地管理大量连接。 **示例代码:** ```c // ...

    理解IO completion port

    IO Completion Port(IOCP)是Windows操作系统提供的一种高级异步I/O机制,特别适用于构建高性能、高并发的网络服务器应用。IOCP允许应用程序以非阻塞的方式处理大量并发的I/O操作,提高了系统的吞吐量和响应能力。...

    MFC IOCP模型异步IO

    IOCP(I/O Completion Port,I/O完成端口)是Windows操作系统提供的一种高效的异步I/O模型,尤其适用于处理大量并发I/O操作。在这个场景中,"MFC IOCP模型异步IO"指的是使用MFC来实现基于IOCP的异步I/O操作。 IOCP...

    介绍当前Windows支持的各种Socket I/O模型

    IOCP 模型 (I/O Completion Port) IOCP模型是一种高级的异步I/O模型,主要用于处理大量并发连接。它使用完成端口来管理异步I/O操作,提供了非常高的性能。 **特点:** - 高性能,适合大规模并发应用。 - 复杂性较...

    IOCPDemo-完成端口I/O模型编程

    完成端口(IOCP,Input/Output Completion Port)是Windows操作系统提供的一种高效的多线程并发I/O模型,尤其适用于网络编程中的高并发场景。在IOCPDemo中,我们将会探讨如何利用这种模型来构建高性能的UDP多播...

    理解IO_Completion_Port(完成端口).

    然而,理解和正确使用 IOCP 需要深入理解 Windows 内核 I/O 模型、线程管理和网络编程原理,因此它对开发者的要求较高。 在实际应用中,除了基本的 I/O 完成端口API之外,还需要关注线程同步、错误处理、资源管理等...

    IOCompletion Port Technique and Asynchoronos IO Operartion

    完成端口(IO Completion Port,简称IOCP)技术是Windows操作系统中用于高并发I/O处理的一种高效机制。它主要用于优化大量的并发I/O操作,尤其在服务器应用中,能够显著提升系统的吞吐量和响应能力。同步IO操作和...

    IOCP-SRC.rar_Completion Port_IOCP_completion_iocp client

    在Windows系统中,Completion Port(完成端口,简称IOCP)是一种高效且可扩展的I/O模型,尤其适用于多线程服务器应用。本文将深入探讨IOCP的概念、工作原理,并通过分析“IOCP-SRC.rar”提供的服务器和客户端源代码...

    IO-Completion-Port.rar_IO_Completion_completion

    IO Completion Port(IOCP)是Windows操作系统中一种高级的I/O模型,主要用于提高多线程服务器应用程序的性能和可伸缩性。IOCP允许应用程序在I/O操作完成时被通知,而不是等待I/O操作完成。这种机制使得系统资源能...

    完成端口(Completion Port)详解

    完成端口(Completion Port,简称IOCP)是Windows操作系统中的一种高级I/O模型,它用于高效地处理大量的并发I/O操作。在TCP/IP编程中,尤其是服务器应用,高并发是常见的需求,IOCP通过异步I/O和事件通知机制,为...

    完成端口(Completion_Port)详解

    ### 完成端口(Completion_Port)详解 #### 一、完成端口的优点 完成端口作为一种高效的网络通信模型,在C/S模式下有着卓越的表现。它通过充分利用Windows内核进行I/O调度,达到了最佳的性能水平。其核心优势在于: ...

    教你玩转网络编程模型之完成例程(Completion Routine)篇配套代码

    在Windows API中,完成例程通常与IOCP(I/O完成端口,I/O Completion Port)结合使用。IOCP是一种高效的多线程I/O管理机制,它可以将多个线程与一个或多个I/O操作关联起来,当I/O完成时,系统会将控制权转移到相应的...

    完成端口(CompletionPort)详解 —— 实例

    完成端口(Completion Port,简称IOCP)是Windows操作系统中的一种高效I/O模型,主要用于处理大量并发的异步I/O操作。在C++编程中,IOCP被广泛应用于网络编程,如服务器应用,以实现高性能的并发处理能力。本文将...

    iocp.zip_IOCP_completion_iocp C++_iocp winsock_iocpserverex

    标题中的"IOCP.zip"指的是一个关于I/O完成端口(I/O Completion Port)技术的压缩包文件,其中包含了C++编程语言实现的Winsock相关的示例代码。这个压缩包包含以下几个子文件: 1. `iocpserverex.cpp`: 这个文件很...

    IO_Port.rar_IO port_IOCP_io完成端口_port io_完成端口

    为了解决这个问题,Microsoft引入了一种高效的I/O模型——I/O完成端口(IOCP,Input/Output Completion Port),它允许多个线程并发处理I/O请求,从而显著提升系统性能。本文将深入探讨IOCP的概念、工作原理以及如何...

    IOCP详细理解

    IOCP(I/O Completion Port)是一种高效的异步I/O模型,广泛应用于Windows平台的各种I/O操作中。为了深入理解IOCP的本质原理,我们需要从多个方面进行探讨。 首先,IOCP机制中存在三个数据结构:投递队列、完成队列...

    vc语言编程之iocp系统

    IOCP(I/O Completion Port)是Windows操作系统中用于处理异步I/O操作的一种高效机制。在VC++编程中,掌握IOCp技术对于构建高性能、高并发的服务器应用至关重要。本文将详细介绍IOCp的工作原理、使用方法以及在VC++...

Global site tag (gtag.js) - Google Analytics