一次序列化与反序列化自有协议的经历(lua版本)

原创 2016年08月30日 16:19:02


之前写过一篇python序列化反序列化的文章(http://blog.csdn.net/q_yang1987/article/details/52194860),最近为这个协议实现了一个lua版本,用这个练手感觉对初学lua的我来说很有价值,本文记录一下这个库的实现细节:


  • 使用
使用时需要先定义Protocol协议结构:

local Proto = require("proto2")

local Phone = Proto.Protocol:new({
        {"number", Proto.String},
        {"money", Proto.UINT32},
    })

local Person = Proto.Protocol:new({
        --{"header", Proto.Header},
        {"uid", Proto.UINT32},
        {"age", Proto.UINT16},
        {"phone_count", Proto.UINT8},
        {"phone", Proto.List:new("phone_count", Phone)},
    })

Proto.Protocol:new出来的是protocol对象,使用的时候需要由Protocol对象生成对应的Message,比如下面的基本用法
local function test_basic()
    local xiaoxiao = Proto.Message:new(Person)
    xiaoxiao.uid = 111000000
    xiaoxiao.age = 22
    xiaoxiao.phone_count = 1
    local phone = Proto.Message:new(Phone)
    phone.number = "2211111"
    phone.money = 100
    xiaoxiao.phone[1] = phone
    print(xiaoxiao)
end

local function test_basic2()
    local Company = Proto.Protocol:new({
            {"header", Person},
            {"count", Proto.UINT32},
            {"employee", Proto.List:new("count", Person)},
        })
    titan = Proto.Message:new(Company)
    titan.header.uid = 1
    titan.header.age = 30
    titan.header.phone_count = 0
    titan.count = 2
    titan.employee[1] = titan.header
    xiaoming = Proto.Message:new(Person)
    xiaoming.uid = 2
    xiaoming.age = 31
    xiaoming.phone_count = 1
    xiaoming.phone[1] = "111222333"
    titan.employee[2] = xiaoming
    print(titan)
enduid=111000000
age=22
phone_count=1
phone=[
<1> number=2211111 money=100 
]

header.uid=1
header.age=30
header.phone_count=0
header.phone=[
]
count=2
employee=[
<1> uid=1 age=30 phone_count=0 phone=[ ] 
<2> uid=2 age=31 phone_count=1 phone=[ <1> 111222 ] 
]
print(message_object)也做了一些友好的输出

pack和unpack函数对应于序列化和反序列化函数,格式兼容之前介绍的python协议
local function test_copy()
    local copy = Proto.Message:new(Person)
    copy:unpack(xiaoxiao:pack())
    print("original", xiaoxiao)
    -- do some modify
    copy.phone_count = 2
    local phone2 = Proto.Message:new(Phone)
    phone2.number = "111111111"
    phone2.money = 100
    copy.phone[2] = phone2
    print(copy)
    
    copy2 = Proto.Message:new(Person)
    copy2:unpack(copy:pack())
    print(copy2)
endoriginal	uid=111000000
age=22
phone_count=1
phone=[
<1> number=2211111 money=100 
]

uid=111000000
age=22
phone_count=2
phone=[
<1> number=2211111 money=100 
<2> number=111111111 money=100 
]

uid=111000000
age=22
phone_count=2
phone=[
<1> number=2211111 money=100 
<2> number=111111111 money=100 
]

  • 关于lua中的int 64

lua在实现uint64时候有一个坑,lua中只有number类型,也就是double 64,在表示UINT64的时候存在精度丢失问题,可以通过下面的代码体现

a = 2000000001 * 2000000001

print(a)

b = 4.000000004e+18

print(a==b)

> true

也就是1丢失了,http://blog.codingnow.com/2012/04/lua_int64.html云风blog里面为了应对这个问题,写了一个库,本文在实现的时候也采用了这个库https://github.com/cloudwu/lua-int64,但在接口使用上遵照云风库的接口(比如从字节初始化,int64对象之间才能进行精确的加减乘除):

local function test_u64()
    local Test64 = Proto.Protocol:new({
            {"u64", Proto.UINT64},
        })
    local t64 = Proto.Message:new(Test64)
    raw = '\1' .. string.rep('\0', 6) .. '\0'
    t64.u64 = raw
    print(t64)
    t64.u64 = t64.u64 / 0x10000 * 0xF
    print(t64)
endu64=int64: 0x100000000000001

u64=int64: 0xF0000000000

实现的时候通过__index, __newindex元方法内部存储为int64,序列化以及反序列化也比较有意思:

unpack = function (self, bytes)
    return i64.new(string.reverse(bytes:sub(1, self.length())), 9
end

pack = function (self, value)
    high = value / 0x10000000
    low = value % 0x10000000
    local bytes = struct.pack(">I", #high)
    local bytes = bytes .. struct.pack(">I", #low)
    return bytes
end
思路就是将64位切成32位,按网络序传输,其中用到的序列化库struct是:http://www.inf.puc-rio.br/~roberto/struct/

做这个库最大的目的就是为了之后为实现lua服务器做网络底层支持,同时也作为学习lua过程的一个练手




版权声明:本文为博主原创文章,转载必须注明出处

解决protobuf-lua导入其他proto的BUG

BUG示例protobuf-lua有个BUG:当import其他proto的消息类型时,会报错假如有两个proto:reward和mail。 其中mail的proto导入了reward的消息类型re...
  • wonbit
  • wonbit
  • 2015年11月16日 18:15
  • 4630

protobuf序列化/反序列化性能及问题

为了tensorflow项目要求测试protobuf序列化/反序列化的性能,测试过程及测试结果如下: 一. 测试环境 python 2.7 + proto3 二. 测试方法 1. 自定义一个prot...

Lua 中实现 protobuf 序列化,反序列化

Protobuf 官方并没有 Lua版本,然后网易的程序猿开发出了 protoc-gen-lua ,可以让我们将 Proto 文件转成 lua 脚本在 Lua中使用,下面是详细的编译、安装、使用教程。...

Lua里实现将table转成字符串(序列化)和将字符串转换回table(反序列化)

--[[ file name : table序列化和反序列化的问题.lua author : Clark/陈泽丹 created : 2011-12-22 ...

Lua中实现php序列化及反序列化函数

好高兴啊,昨天翻遍了lua自带的库,又在网上找了一天如何在lua中序列化以及反序列化,但结果都不是我要的,因为我要在lua中反序列化由php序列化函数序列化的一个字符串,比如这样的: a:9:{...

Protobuf Lua 版本 和 C#版本序列化数据不一致

使用 protoc-gen-lua 把protobuf 嵌入到项目中,项目中原来使用的是 Unity版本的protobuf ,需要并存,所以测试 protobuf 在两个平台序列化出来的数据是否一致。...

Lua序列化

概念普及 持久化 持久化(Persistence),即把内存中的对象保存到可永久保存的存储设备中。持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中...

lua Table的序列化与反序列化函数

table.tostring = function(t) local mark={} local assign={} local function ser_table(tbl,par...

[lua/unity/cocos2dx]关于云风pbc不支持int64的解决办法

其实这个很简单,因为源码都有,改改就好,但是估计有些人很担心改了之后出现各种问题解决不了,我通常是先改,出问题再说,哈哈。不过其实去看看源码,云风的代码还是写的很清晰的 以上是废话 找到pbc-l...

protobuf-gen-lua 不能支持int64 的解决方法 !!

protobuf-gen-lua 不能支持int64,序列化的时候数据出错,少了一个字节。很大概率出现。 不知道是 Lua5.1.4的问题还是 protobuf-gen-lua 的问题。 后面有...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一次序列化与反序列化自有协议的经历(lua版本)
举报原因:
原因补充:

(最多只允许输入30个字)