分类: GameEngine专题之IOCP(完成端口)2010-04-06 14:44 2611人阅读 评论(0) 收藏 举报

本文作者:sodme
本文出处:http://blog.csdn.net/sodme
声明:本文可以不经作者同意任意转载,但请保留文章开始前的作者、出处及声明信息。谢谢。

  由于个人工作的关系,接触高性能服务器的研发已经有一段时间了,在没有接触这个话题之前,我也和许多人一样,认为服务器的设计无非就是用一下winsock,调用调用函数那么简单。当亲自完成了一个在win平台上能承载上万连接的测试模型后,才知道,原来,作高性能服务器是这么有挑战性。你不仅需要在细支末节上对模型进行精雕细琢,更需要在总体架构方面进行权衡选择。这两方面,都会影响到你的服务器性能的正常发挥。作为对“细枝末节”方面的介绍,请参照我之前写的系列文章“完成端口之性能优化”。而从此篇文章开始的系列文章,将就一个完整的高性能服务器模型进行介绍,而对于服务器集群架构方面,则不在此系列的讨论范围,那将是未来数周我将要完成的事。有朋友跟我说,希望我能提供底层模型的完整代码或可供使用的动态链接库及LIB文件。对于这个要求,我现在还在考虑之中。确实,有了代码,要学得更快一点,但由于模型里牵涉到一定的版权问题,所以,我会考虑将其进行必要的修改,而后再考虑是否向大家提供源代码。不过,可以肯定的是,对于LIB及DLL的要求,我想我会尽快提交上来的。

  所谓的“高性能”,我想不外乎两个方面:
  1、处理的并发请求要尽可能地多,具体表现为同一时间内同时连接的客户端数量;
  2、数据包的吞吐量要尽可能地大,具体表现为单位时间内服务器的收、发数据量。

  win平台下,IOCP(完成端口)是处理大量并发连接的最佳处理方案,所以,此后讨论的文章,也是基于这个模型的。有关一个独立的IOCP模型到底是如何工作的,请大家下载微软的SDK,在那个例子里,有基本的IOCP示例。但那仅仅是个示例,于实际的应用中,还需要作很多工作。阅读以下的内容时,最好具备以下条件:知道IOCP的基本概念,以及它所调用的几个必备函数(Create、Get、Post函数等)的使用。注:为嫌麻烦,这几个函数,我采用的都是简单叫法,完整的函数名请查看完成端口相关资料。

  为了使大家能有一个宏观概念的把握,我先介绍一下基于三层结构的服务器通信底层模型。对于软件架构而言,没有最好之说,放在不同的应用环境其表现都可能千差万别,所以,我不保证这个架构是能让所有人都看着舒服的,我只保证,在我当前的项目应用中,这个架构充分考虑了“性能”和“可扩展性”两者的兼顾,让我在很容易地开发新的服务器时,仍然可以享受到很好的性能。

  一、三层架构图及简单说明

  三层架构图如下:
         CIOCPServer
         ||
         ||
      CCutomHPServer
         ||
         ||
       CTestServer

  以后我们要讨论的就是这个看上去并不复杂的三层架构图,下面就此架构图中的主要类进行简要说明。

  CIOCPServer:
  完成端口服务器基本通信类,它使用winnt/2000/xp平台特有完成端口特性,对通信模型进行封装,向它的派生类提供以下基本扩展接口(可被重载的虚函数):

  1、有客户端连接时的处理接口;
  2、客户端断开时的处理接口;
  3、从客户端收完数据后的处理接口;
  4、向客户端发送完数据后的处理接口;
  5、网络通信及服务器处理出现错误时的处理接口。

  CCustomHPServer:
  典型的高性能服务器类,CIOCPServer是其基类之一(之一?难道还有另外的基类,回答是:当然,呵呵,别急,后面会介绍),此类在CIOCPServer的基础上,封装了三个数据队列及三类处理线程,介绍如下:

  1、接收数据包队列及接收线程:用于存放刚收到的数据包,此数据包还没有进行逻辑意义上的拆解,接收线程从此队列中取出数据包,并将其形成一个逻辑意义上完整的数据包加入到“处理数据包队列”中;

  2、处理数据包队列及逻辑处理线程:已经拆解成了逻辑意义上的数据包,逻辑处理线程对此类数据包进行逻辑解析,这里就是服务器的主要逻辑部分,有的数据包在处理完成后,可能是需要向客户端返回处理结果的,此时就需要逻辑线程在处理完成后将返回结果的数据包放入“发送数据包队列”中;

  3、发送数据包队列及发送线程:待发送的数据包队列,由发送线程根据数据包里的客户端套接字发送给特定客户端。

  CTestServer:
  此类是一个测试类,主要用于演示如何在CCustomHPServer的基础上派生一个真正的应用服务器,并用于说明它需要重载实现CCustomHPServer的哪些重要虚函数。

  基于以上的结构,我们的服务器通信模型,可以一层一层地实现,一层一层的测试。在CIOCPServer中,它本身是不带有任何数据队列的,所有的网络数据都是即来即处理,没有保存数据,实现的是即时响应。在CIOCPServer里,有两类重要线程:AcceptThread线程和WorkerThread线程。其中,AccetpThread线程使用Accept或AcceptEx函数来接收客户端的连接请求,并实现客户端socket与完成端口句柄的绑定,“有客户端连接时的处理接口”就是在这里封装的;而WorkerThread线程是我们在完成端口中常说的“工作者线程”,它由get函数触发工作,除“有客户端连接时的处理接口”之外的其它接口,都在这里进行封装。

  在真正实现一个高性能服务器模型时,我们可能需要逐层地加以实现,这样作,一是因为测试起来要简单一些,二是因为在我们逐层实现时可以清楚地知道每一层在实现时的效率是什么样的,这样就有利于我们找出提高效率的突破口。可以先从CIOCPServer类开始,实现一个简单的ECHO服务器,即:回显服务器。不用维护数据包队列,对客户端发过来的数据,即时返回给客户端。作完这一层,属于完成端口该作的事基本上就作完了,它包括:有大量客户端连接时的客户端连接队列维护,客户端连接、断开、发送、接收数据时的事件处理及线程同步。根据我的经验,在处理底层的客户端断开事件时是一个难点,新手往往会在接收到断开事件时直接释放掉当前客户端对象,但比较好的作法是使用引用计数机制,而不是直接释放。另外,在“释放”这一点上,我也有自己的一个看法,即:客户端对象最好不要释放,而把它放入闲置队列或者关闭原来的socket之后,再重新生成一个新的socket让它与原客户端对象关联,把它作为一个新的客户端对象使用,这样就避免了频繁的客户端对象的建立与释放,当然,这样作的前提是在接受客户端连接方面最好使用AcceptEx函数而不是Accept。

IOCP三层结构的更多相关文章

  1. Atitit.软件开发的三层结构isv金字塔模型

    Atitit.软件开发的三层结构isv金字塔模型 第一层,Implements 层,着重与功能的实现.. 第二次,spec层,理论层,设计规范,接口,等.流程.方法论 顶层,val层,价值观层,原则, ...

  2. C#-WebForm-WebForm开发基础、如何给控件注册事件?——事件委托写法、http无状态性、三层结构

    (小知识 - xml:可扩展的标记语言 html:超文本标记语言) 一.创建WebForm:新建→网站 此时文件夹中只有一个 config 文件,打开后 二.在项目下右键添加新项 在设计页面中打开 从 ...

  3. 在VS2010中建立C#三层结构

    转自:http://www.blueidea.com/microsoft/vs2010/2010_con/2010081301.htm 三层结构,会有多个项目.为了让各项目之间的关系反映在目录结构上所 ...

  4. android的四层体系结构,基于mvc三层结构浅析

    从多方面理解Android体系结构 1.以分层的方式来看Android 安卓体系结构分为四层. 首先看一下官方关于Android体系结构的图: 1).Linux Kernel:负责硬件的驱动程序.网络 ...

  5. mvc与三层结构

    http://www.cnblogs.com/zhhh/archive/2011/06/10/2077519.html 又看到有人在问三层架构和MVC的关系,感觉这种问题有点教条化了.因为它们都在逻辑 ...

  6. mvc与三层结构终极区别

    http://blog.csdn.net/csh624366188/article/details/7183872 http://www.cnblogs.com/zhhh/archive/2011/0 ...

  7. java中从Spring、Hibernate和Struts框架的action、service和dao三层结构异常处理体系设计

    Spring的事务实现采用基于AOP的拦截器来实现,如果没有在事务配置的时候注明回滚的checked exception,那么只有在发生了unchecked exception的时候,才会进行事务回滚 ...

  8. JavaWEB 常用开发模式MVC+三层结构

    MVC开发模式: M:  Model   -- JavaBean C:  Controler   --  Servlet V: View   --- JSP 不会在word里面画画,所以就直接截了 老 ...

  9. 传统三层结构和MVC之于贫血模式和充血模式以及领域建模

      相信很多人跟我一样,一开始在使用贫血模式的三层结构:抽象出来一个贫血的实体封装,然后把对模型的所有操作,分离出来,分离到BLL层去,然后DALL层负责把这些操作和数据库产生映射,负责读写删改的操作 ...

随机推荐

  1. spring-boot-route(一)Controller接收参数的几种方式

    Controller接收参数的常用方式总体可以分为三类.第一类是Get请求通过拼接url进行传递,第二类是Post请求通过请求体进行传递,第三类是通过请求头部进行参数传递. 1 @PathVariab ...

  2. [Angular JS教程] HeroService: getHeroes failed: undefined 问题解决方法

    最近在学习入门Angular JS,学习资源是https://angular.cn/tutorial, 在学习到 "https://angular.cn/tutorial/toh-pt6模拟 ...

  3. 如何用5000行JS撸一个关系型数据库

    首先声明,我不是标题党,我真的是用5000行左右的JS实现了一个轻量级的关系型数据库JSDB,核心是一个SQL编译器,支持增删改查. 源代码放到github上了:https://github.com/ ...

  4. STM32之旅2——按键

    STM32之旅2--按键     几乎每个项目都有用到按键,为了避免以后在做大项目的时候还在琢磨按键怎么写,现在写一个,方便以后使用.这里是最简单的独立按键驱动方法,和学习51单片机是的一样,更好的方 ...

  5. 记录小坑-tp5 使用模型select查询

    场景: 使用模型去select查询后进行业务处理 再进行 saveAll 提示缺少更新条件 坑点:此时取出的数据结构是 query对象 { array:[ xxxx => xxx ] }: sa ...

  6. 【idea&spring mvc】搭建简易的spring mvc项目(基于maven)!

    一.创建项目 1.打开idea,file--new--project 2.按照步骤①②③④操作 3.输入包名,并点击下一步 4.选择下载包的maven的setting.xml配置路径和包的存放地,然后 ...

  7. composer 打印美化

    { "name": "brady_frmwork", "description":"php framwork", &qu ...

  8. 第六章 Linux系统之文件管理

    一.文件管理概述 1.对文件做些什么? 谈到Linux文件管理,首先我们需要了解的就是,我们要对文件做些什么事情? 其实无非就是对一个文件进行创建.复制.移动.查看.编辑.压缩.查找.删除等等 2.内 ...

  9. 第10天 | 12天搞定Python,文件操作(超详细)

    在开发系统的过程中,经常会用到XML存储和传输数据,XML是一种用于标记电子文件使其具有结构性的标记语言,在博客中经常会见到. JSON是一种轻量级的数据交换格式,常被用在后端和前端的数据交互上,如你 ...

  10. Jmeter入门(3)- Jmeter录制脚本

    一. 录制web端 1. Badboy的介绍和安装 1.1 使用第三方工具Badboy来录制. 免费的web自动化测试工具 一个浏览器模拟工具 主要进行脚本的录制和回访,和对录制脚本进行调试,可以将脚 ...