分类: 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. mysql-11-DML

    #DML语言 /* 数据操作语言 插入:insert 修改:update 删除:delete */ #一.插入语句 /* 语法: insert into 表名(列名...) values(新值...) ...

  2. Copy As HTML From VSCode

    JS生成可自定义语法高亮HTMLcode cnblogs @ Orcim  !deprecated! 这里有更好的方案,具体看我的这篇博客博客代码高亮的另一种思路 这篇文章介绍了如何在博客里插入一段 ...

  3. 剑指Offer(一):二维数组中的查找

    一.前言 刷题平台:牛客网 二.题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整 ...

  4. 《C++primerplus》第9章练习题

    1.(未使用原书例题)练习多文件组织.在一个头文件中定义一种学生的结构体,存储姓名和年龄,声明三个函数分别用于询问有多少个学生,输入学生的信息和展示学生的信息.在另一个源文件中给出所有函数的定义.在主 ...

  5. winfrom加载自定义控件、窗口pannel后闪烁问题

    我用一个panel当容器,里面有好多控件,加载的时候一直闪烁. 借鉴网友的思路: 窗口初始化界面加入代码 this.DoubleBuffered = true;//设置本窗体   SetStyle(C ...

  6. 详解Class加载过程

    1.Class文件内容格式 2.一个class文件是被加载到内存的过程是怎样的? loading 把一个class文件装到内存里,class文件是一个二进制,一个个的字节 linking Verifi ...

  7. Linux配置Docker

    Centos6.8 1.查看自己的内核 [1].uname [root@host79 ~]# uname -r 2.6.32-642.el6.x86_64 [2].查看CentOS版本信息 CentO ...

  8. Jenkins从节点上构建自动化测试项目时报错:java.io.IOException: Unexpected termination of the channel

    在mac电脑上配置了Jenkins从节点,在该从节点上构建app UI 自动化测试项目,运行一些用例后报如下错误: java.io.EOFException at java.io.ObjectInpu ...

  9. IP协议那些事

    IP协议作为通信子网的最高层.提供无连接的数据报传输机制. IP协议的作用 寻址和路由 传递服务:提供不可靠,无连接的服务. 为什么说IP协议不可靠.无连接 不可靠:是指不能保证IP数据包能成成功到达 ...

  10. vi/vim系统编辑命令使用技巧

    01前言 在Linux系统中会有很多的文件信息,这些文件的内容如果需要编辑,就必须借助vi或vim编辑命令. vi是Linux命令行界面下的重要文字编辑器.vim是vi命令的增强版. [语法格式] v ...