http://blog.csdn.net/herm_lib daemon.huang # gmail # com
2.1 概述
本章从网络通信组件的结构开始,简单地介绍一种较常用的通信组件结构。接着结合通信组件的结构来说明Framework的实现,描述Framework的对象模型,Network、Peer和Session。最后,分析Framework实现的时候采用了哪些措施保证性能,以及哪些地方还可以继续提高性能。最后给出安全措施。
2.2 网络通信组件
一个网络应用程序很多情况下简单地分成两层:逻辑层和网络层,其关系如下:
+---------------+
| 逻辑层 |
------------------
| 网络层 |
+---------------+
本节要介绍的网络通信组件就是这里网络层的实现。
一个网络通信组件一般包含下面3个层次:
1) 接收和发送消息包(Message)
通过Socket API从网络接口接收和发送UDP数据报或者TCP的数据流。
2) 消息包缓冲区
大部分应用程序需要一个消息包缓冲区,这个缓冲区可以平衡收发与逻辑层处理速度的不匹配。
3) Dispatch消息
网络组件的消息交给应用前的一个预处理;应用逻辑数据往下走时,也有可能在这一层作必要的处理。
2.3 Herm Framework
Herm Framework重点是实现一套FreeBSD&Linux上的高性能通信组件,实现了一个通用的网络层的功能,逻辑层通过几个C++接口操作组件内部功能。
Framework采用多路复用的机制实现数据的收发,Linux上用epoll,FreeBSD上用的是kqueue,Windows上是select。从实现可以肯定,在Windows上仅支持63个的TCP连接,不适合开发高并发的TCP Server;但开发UDP Server没问题。Framework内部会创建一个线程实现数据收发,这样在多核的机器中可以较充分的利用CPU。
Framework内部的消息缓冲区用的是一读一写non-lock的ring buffer,实现见utils/buffer.h&buffer.cpp。
对象模型
Herm Framework采用面向对象的方法抽象了网络组件的几个部分。Framework抽象出了Network, Peer和Session三种对象。
一个Network维护一个线程环境和控制一个或多个Peer对象;Peer可以认为是一个TCP Client、TCP Server、UDP Client或UDP Server的抽象,管理一个或多个Session;而Session就是TCP的一个连接或者是UDP的数据交互的两端。
2.4 性能和安全考虑
性能和简单有时候是一对矛盾,要保证性能,可能会使代码实现相对来说变得复杂一些。和Framework性能有关的有三方面:多路复用的收发机制、多线程对公共buffer读写加锁问题、数据拷贝次数以及对象的内存管理。
Linux的epoll有LT&ET模式,Framework通过一个编译宏让使用决定是否使用,从而达到数据收发的最高效。buffer的读写加锁的问题,Framework的做法是通过设计的方式避免加锁,消除加锁解锁是的性能损耗。
数据拷贝次数是很重要的一个性能关注点,理想的情况是,通信组件将某个Session的消息包交给逻辑层后,只经历一次内存拷贝,就是协议栈buffer到应用层空间的一次拷贝,就是调用Socket API recv()那一次拷贝。在写本文的时候,Framework内部是两次内存拷贝,另外一次是组件将消息包传给逻辑层时,作了一次拷贝。这是一种折中的方式,折中性能与实现复杂度、调用安全。直接将组件的消息包的地址传给逻辑层,实际使用的时候有些约束条件,使用不当会产生严重的错误。
最后就是对象的内存的管理问题,在一个TCP Server中,有时候有几W个Sessions,对象的管理对性能影响是很大的。Framework的实现的原则是,系统初始化是,所有的对象都已经预创建完成,在系统运行的过程中,绝对不允许对象的动态创建或销毁。但像Peer对象,考虑一个TCP Server的Peer,他是相当稳定的,所以在Network对象中,就直接用std::list管理,简单直接,代码容易维护。
安全方面主要是非法消息包控制,当各种网络对象出现不合法的状态是,严格地控制方法等。
下一章详细地介绍用Framework实现TCP Server&Client/UDP Server&Client。