当前位置:C++技术网 > 精选软件 > 云平台开发架构分析系列:4 数据包的处理逻辑分析1

云平台开发架构分析系列:4 数据包的处理逻辑分析1

更新时间:2017-06-20 08:42:46浏览次数:1+次

    在《云平台开发架构分析系列3:libuv包装服务类回调机制分析》中已经将libuv实现的TCP服务器端的功能跑起来了。我们也自己实现了新连接处理回调函数和接收到客户端发送过来的数据的回调函数。到这一步,TCP服务器端已经搭建起来了。而业务的实现,则是根据不同的业务来的。一般不同的业务都有不同的协议。我们接受的数据,也就是定义的协议数据包。对于行业具体的协议相关的分析就不在这里写,没有通用意义。不过,在解析数据包还有一层通用的流程,下面就这个做一个分析。
    先看看处理流程:
    云平台开发架构分析系列4:数据包的处理逻辑分析
    我们在自己定义的接受数据的回调函数中,就会得到原始数据。回调函数接受三个参数,如下:
void recv_cb(int client_id, const char* buf, int buf_size);
    第一个参数是客户端ID,第二个参数是底层传上来的缓存地址,第三个参数是缓存的大小。在上一篇文章中我们知道,通过客户端ID我们就可以查找到对应的套接字,这样就可以和客户端通信了。我们在处理完数据后,就可以通过客户端ID回复客户端。
    缓存buf自然就是接受到的数据了,我们就是要处理这里的数据。处理数据有几件事要做:
1.拆分数据包
2.验证数据包合法性
3.不完整数据包缓存拼合
4.按照业务规则解析数据包
5.按照业务规则回复客户端
    为什么要拆分数据包呢?我们需要清楚一件事,虽然TCP提供可靠的数据通信,但是数据包重叠是很正常的事情。如果网络不稳定或者拥塞,就会导致准备发送的数据包延迟发送。然后后续又有很多数据包集中起来,最后就会拼合为一个大数据包发送出去。当网络不稳定的时候,这样的大数据包也会集中收到,最后传给recv_cb函数时也就是一大段数据包。这个包按照接受的顺序依次排列着业务数据包。有时候可能几个数据包都是完整的,有时候可能不巧,刚好将一个数据包从中间截断了,再后续的数据包中开始部分有后半段。
    一开始做数据包解析的时候,我们很可能会因为经验不足,认为底层上传过来的数据包都是单个单个的。我们有的客户在做协议数据包的解析的时候,竟然不会处理叠加数据包的情况。说是让我们确保每次只发一个数据包。让我们也是很无语。我们应用层是无法确保的。数据包在网络发送过程中是不确定的,网络不稳定都会造成数据包重叠在一起。我们可以形象的将两个数据包前后叠在一起的情况称为粘包。就好像两个数据包身上有胶水一样,粘在一起。
    所以,我们处理数据包的时候,不是简单的将接收到的数据当做一个数据包来解析。否则会将后面的数据包丢掉或者直接认为数据包的长度错误而丢弃,这样就造成了数据丢失了。
    我们将数据包挨个拆开,我们称之为拆包。将数据包一个个拆开后,我们就要对这个数据包进行合法性验证了。合法性验证就需要根据我们定义的业务协议来分析了。比如开头标志、序列号、校验码、包长度等等。只要不符合规定,就可以将数据包丢掉。因为这个是对数据包正确性和安全性的验证。不正确的报文不能按照正常的报文处理,否则会带来严重的逻辑错误。而对各种标志的检测和校验,也是防止恶意攻击,拦截和篡改数据包。为了提高安全性,我们可以加入加密规则,将协议数据包按照规定的办法加密,这样也是确保数据安全必须的。不过我们这里就不介绍加密部分了。
    如果出现叠加数据包,拆成多个单个的数据包,然后挨个的解析包就行了。然而如果是不完整的数据包呢?我们不能简单的将这个数据包丢掉,因为这个不代表数据包不完整,很可能是底层在叠加多个数据包时刚好将一个数据包截断了,后半段在后续的数据里。所以这样的数据包一样还是有效的。所以我们需要将这样的半段数据包缓存起来。在后续的数据包来的时候,然后和前面缓存的数据拼成一个完整的数据包,再进行数据包的检验,如果合法,就继续解析,如果不合法就丢弃。当然,如果只是长度不够长,有可能是还有没有接受到的数据,此时要继续缓存,知道所有的数据都接受完毕才行。如果长度符合要求,数据本身不对,那么就是无效的数据包了。
    拆完数据包后,校验通过了,那么就得到一个完整的有效数据包。我们此时就要对数据包进行解析。我们在校验数据包的时候是按照业务协议的数据包的包头进行校验的。而我们解析数据包则是解析数据包里的数据字段,字段中不同的数据代表不同的含义,这是协议定义的,我们需要解析出来,再进行业务逻辑处理。
    实际上一般业务协议都是一个个的命令。业务协议的数据部分都是命令的相关参数。解析出来命令和命令参数,我们就执行对应的逻辑。
    最后解析完后,我们也要按照业务逻辑构建一个数据包,然后发给对应的客户端,从而完成交互。
    从整体上,也就是这样一些流程。有些你知道,有些你不知道。就比如说叠包拆包的问题,没有经验的人就不清楚。我们后面再来具体分析如何拆包。而业务逻辑处理就没法分析了。每一个行业都不一样,而且这个是与公司有关的东西了,就不能说了。而基础的经验,则没有关系。
    而且对于关键代码我也不可能给出来的,这些代码都受到保护,不能贴出来。需要描述的时候,只能写伪代码,交代流程。而且这些代码写出来意义也不大。你看这系列文章是去获取整体的技术架构,不要深入钻研某一个具体的细节。当你将整个架构掌握了,可以自己写代码慢慢实现。