一次python序列化与反序列化自有协议的经历

来源:互联网 发布:编程智能机器人玩具 编辑:程序博客网 时间:2024/06/06 00:27


目前在做的一个老项目,使用的网络协议是自有协议,序列化与反序列化都需要手写代码,而且是C++的。由于新设计了一个python服务器,需要解析相应的网络协议封包,决定不能再这么蛮干了(毕竟python),目标是相应的序列化与反序列化不再需要干预,只需要定义封包格式就好。

  • 使用方式

先上实现后的使用方式:

    • 定义结构
class Phone(BaseProtocol):                                                                                                                                                                                                                                                                  def __init__(self):                                                                                                                             BaseProtocol.__init__(self)                                                                                                                 self.AppendDef("number", FixedSizeString, 16)                                                                                               self.AppendDef("left_money", UINT32)

class Person(Protocol):                                                                                                                                                                                                                                                                     def __init__(self):                                                                                                                             Protocol.__init__(self)                                                                                                                     self.AppendDef("uid", UINT32)                                                                                                               self.AppendDef("age", UINT16)                                                                                                               self.AppendDef("phone_count", UINT8)                                                                                                        self.AppendDef("phone", List, self, "phone_count", Phone)


不需要额外手写序列化代码

    • 使用
其中payload省略了封包头,pack函数就是序列化操作,输出结果:
Person.uid -> 1002Person.age -> 11Person.phone_count -> 2Person.phone._0.number.len -> 7Person.phone._0.number.val -> 1111000Person.phone._0.left_money -> 33Person.phone._1.number.len -> 8Person.phone._1.number.val -> 11112222Person.phone._1.left_money -> 34HW����>�            111100011112222"


  • 实现
网络协议反序列化比较需要处理的地方是可变长度的对象数组,其长度信息一般都会在其它字段中声明,也导致了同类型的每个封包长度不一
python作为一门特别灵活的语言,可以在需要的时候获取这个属性,所以定义的时候可以只指定需要访问的字段名:

self.AppendDef("phone", List, self, "phone_count", Phone)



为了实现类似于数组方式的存取玩法:

p.phone_count = 2                                                                                                                           p.phone[0].number.setStr("1111000")                                                                                                         p.phone[0].left_money = 33                                                                                                                                                                                                                                                              p.phone[1].number.setStr("11112222")                                                                                                        p.phone[1].left_money = 34




需要使用__getitem__以及__setitem__两个方法:
def checkcount(self):    if self.count != -1:        return    self.count = getattr(self.obj, self.key)    for i in range(self.count):        self.AppendDef('_%s' % i, self.cls, *self.args)def __getitem__(self, idx):    self.checkcount()    return getattr(self, '_%s' % idx)def __setitem__(self, idx, value):    self.checkout()    setattr(self, '_%s' % idx, value)

checkcount函数在此时才确定list的数量并生成一系列的_0, _1 ..... _n属性,模拟list

在protobuf、json等等序列化协议盛行的时代,自有协议的设计貌似没有太大的价值,但是设计并理解一套协议对于自我提升很有帮助,同时提高了协议的安全性,也对于维护或者对接一些老系统而不得不使用自有协议时也是必要的。

0 0
原创粉丝点击