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


目前在做的一个老项目,使用的网络协议是自有协议,序列化与反序列化都需要手写代码,而且是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)


 

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

    • 使用
p = Person()                                                                                                                                   
p.uid = 1002                                                                                                                                   
p.age = 11                                                                                                                                     
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                                                                                                                  
                                                                                                                                                                                              
print p.payload                                                                                                                             
print p.pack()
其中payload省略了封包头,pack函数就是序列化操作,输出结果:
Person.uid -> 1002
Person.age -> 11
Person.phone_count -> 2
Person.phone._0.number.len -> 7
Person.phone._0.number.val -> 1111000
Person.phone._0.left_money -> 33
Person.phone._1.number.len -> 8
Person.phone._1.number.val -> 11112222
Person.phone._1.left_money -> 34

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值