一个简单的IOCP(IO完成端口)服务器/客户端类(中文版)

本文档介绍了使用IO完成端口(IOCP)技术创建高效的多客户端服务器/客户端类。IOCP允许高效处理多个连接,解决线程同步问题,并通过异步I/O提供高吞吐量。内容涵盖了IOCP的基本原理、实现细节,包括CompletionKey、OVERLAPPED参数的使用,以及在处理数据包重排序、内存管理和线程同步中的挑战与解决方案。源代码示例提供了IOCP服务器/客户端实现,可用于文件传输和其他通信功能。
摘要由CSDN通过智能技术生成

一个简单的IOCPIO完成端口)服务器/客户端类

——A simple IOCP Server/Client Class By spinoza

原文【选自CodeProject

http://www.codeproject.com/Articles/10330/A-simple-IOCP-Server-Client-Class

源代码:

http://www.codeproject.com/KB/IP/iocp_server_client/IOCP-Demo.zip

http://www.codeproject.com/KB/IP/iocp_server_client/IOCP-SRC.zip

 

——译: Ocean Email: Ocean2oo6@hotmail.com

http://blog.csdn.net/witch_soya/article/details/6978856

http://blog.csdn.net/dongzhongshu/article/details/5645179

http://blog.csdn.net/babelan/article/details/4588608

http://820808.blog.51cto.com/328558/66664

http://820808.blog.51cto.com/328558/68200

This source code uses the advanced IOCP technology which can efficiently serve multiple clients. It also presents some solutions to practical problems that arise with the IOCP programming API, and provides a simple echo client/server with file transfer.

 

1.1要求

l  本文希望读者对C++TCP/IPSocket编程,MFC以及多线程比较熟悉

l  源代码使用Winsock2.0以及IOCP技术,因此需要:

Windows NT/2000 or later: Requires Windows NT 3.5 or later.

Windows 95/98/ME: Not supported.

Visual C++ .NET, or a fully updated Visual C++ 6.0.

1.2 摘要

当你开发不同类型的软件时,你总会需要进行C/S的开发。完成一个完善的C/S代码对于编码人员来说是一件困难的事情。本文给出了一个简单的但是却是却十分强大的C/S源代码,他可以扩展成任何类型的C/S程序。源代码使用了IOCP技术,该技术可以有效地处理多客户端。 IOCP 对于“一个客户端一个线程”所有面临的瓶颈(或者其他)问题提出了一种有效的解决方案,他只使用少量的执行线程以及异步的输入输出、接受发送。IOCP计数被广泛的用于各种高性能的服务器,如Apache等。源代码同时也提供了一组用于处理通信的常用功能以及在C/S软件中经常用到功能,如文件接受/传输功能以及逻辑线程池操作。本文将主要关注一种围绕IOCP API在实际中的解决方案,以及呈现源代码的完整文档。随后,我将展示一个可以处理多连接和文件传输的echo C/S程序。

2.1 介绍

本文阐述了一个类,他可以被同时用于客户端和服务器端代码。这个类使用IOCP(Input Output Completion Ports)以及异步(non-blocking) 功能调用。源代码是基于很多其他源代码和文章的。

 

使用此源代码,你可以:

·为多主机进行链接、或者链接到多主机的客户端和服务器

·异步的发送和接受文件

·创建和管理一个逻辑工作线程池,他可以处理繁重的C/S请求或计算

 

找到一段完善的却又简单的、可以处理C/S通信的代码是一件困难的事情。在网络上找到的代码要么太过于复杂(可能多于20个类),或者不能提供有效的效率。本代码就是以简单为设计理念的,文档也尽可能的完善。在本文中,我们可以很简单的使用由Winsock 2.0提供的IOCP技术,我也会谈到一些在编码时会遇到的棘手的问题以及他们的解决方法。

2.2 异步输入输出完成端口(IOCP)的介绍

一个服务器程序要是不能同时处理多客户端,那么我们可以说这个程序是毫无意义的,而我们为此一般会使用异步I/O调用或者多线程技术去实现。从定义上来看,一个异步I/O调用可以及时返回而让I/O挂起。在同一时间点上,I/O异步调用必须与主线程进行同步。这可以使用各种方式,同步主要可以通过以下实现:

·使用事件(events) 只要异步调用完成,一个Signal就会被Set。这种方式主要的缺点是线程必须去检查或者等待这个eventSet

·使用GetOverlappedResult功能。这种方式和上面的方式有同样的缺点。

·使用异步例程调用(APC)。对于这种方式有几个缺点。首先,APC总是在调用线程的上下文被调用的,其次,为了执行APCs,调用线程必须被挂起,这被成为alterable wait state

·使用IOCP。这种方式的缺点是很多棘手的编码问题必须得以解决。编写IOCP可能一件让人持续痛苦的事情。

2.2.1 为什么使用IOCP?

使用IOCP,我们可以克服”一个客户端一个线程”的问题。我们知道,这样做的话,如果软件不是运行在一个多核及其上性能就会急剧下降。线程是系统资源,他们既不是无限制的、也不是代价低廉的。

IOCP提供了一种只使用一些(I/O worker)线程去“相对公平地”完成多客户端的”输入输出”。线程会一直被挂起,而不会使用CPU时间片,直到有事情做为止。

2.3 什么是IOCP?

我们已经提到IOCP 只不过是一个线程同步对象,和信号量(semaphore)相似,因此IOCP并不是一个复杂的概念。一个IOCP 对象是与多个I/O对象关联的,这些对象支持挂起异步IO调用。知道一个挂起的异步IO调用结束为止,一个访问IOCP的线程都有可能被挂起。

3. IOCP是如何工作的?

要获得更多的信息,我推荐其他的一些文章(译者注,在CodeProject

当使用IOCP时,你必须处理三件事情:将一个Socket关联到完成端口,创建一个异步I/O调用,与线程进行同步。为了获得异步IO调用的结果,比如,那个客户端执行了调用,你必须传入两个参数:the CompletionKey 参数, OVERLAPPED结构。

3.1 CompletionKey参数

第一个参数是CompletionKey,一个DWORD类型值。你可以任何你希望的标识值,这将会和对象关联。一般的,一个包含一些客户端特定对象的结构体或者对象的指针可以使用此参数传入。在源代码中,一个指向ClientContext结构被传到CompletionKey参数中。

3.2 OVERLAPPED 参数

这个参数一般用于传入被异步IO调用使用的内存buffer。我们必须主意这个数据必须是锁在内存的,不能被换页出物理内存。我们稍后会讨论这个。

3.3 socket与完成端口绑定

一旦一个完成端口创建,我们就可以使用CreateToCompletionPort方法去将socket绑定到完成端口,这看起来像这面这样:

BOOL IOCPS::AssociateSocketWithCompletionPort(SOCKET socket,

              HANDLE hCompletionPort, DWORD dwCompletionKey)

   {

      HANDLE h = CreateIoCompletionPort((HANDLE) socket,

            hCompletionPort, dwCompletionKey, m_nIOWorkers);

      return h == hCompletionPort;

   }

3.4 创建异步IO调用

创建真正的异步调用:可以调用WSASend,WSARecv。他们也需要一个WSABUF参数,这个参数包含一个指向被使用的buffer的指针。首要规则是,当服务器/客户端试图调用一个IO操作时,他们不是直接的操作,而是先被传送到完成端口,这将会被IO工作线程去完成操作。之所以要这样做,我们是想要CPU调用更加公平。 IO调用可以通过发送(Post)状态到完成端口来实现,看一下代码:

         BOOL bSuccess = PostQueuedCompletionStatus(m_hCompletionPort,

                      pOverlapBuff->GetUsed(),

                      (DWORD) pContext, &pOverlapBuff->m_ol);

3.5 与线程同步

IO工作线程同步是通过GetQueuedCompletionStatus方法完成的(代码如下)。该方法也提供了CompleteKey参数以及OVERLAPPED参数:

BOOL GetQueuedCompletionStatus(

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值