一次序列化与反序列化自有协议的经历(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过程的一个练手




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

基于Lua的游戏服务端框架简介

本文所述内容,并不涉及服务器集群的进程划分与拓扑结构. 为理解方便,我们假定服务器集群划分为如下的这些进程(跟鹅厂其他游戏项目大同小异): -            router: 数据转...
  • lalate
  • lalate
  • 2016年05月25日 15:31
  • 9843

项目后期Lua接入笔记05--网络协议protobuf在lua中的使用pbc

作为一个网络游戏,不可避免的要和服务端进行数据交互,在数据结构上protobuf是一个不错的方案,在lua中使用protobuf有多种方案可供选择,这里使用的是云风的pbc.先去这个网址下载生成工具h...
  • suifcd
  • suifcd
  • 2017年03月29日 19:57
  • 1388

使用Lua的扩展库LuaSocket用例

目录结构 LuaSocket 是 Lua 的网络模块库,它可以很方便地提供 TCP、UDP、DNS、FTP、HTTP、SMTP、MIME 等多种网络协议的访问操作。 它由两部分...
  • h1023417614
  • h1023417614
  • 2016年08月24日 10:19
  • 5424

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

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

Ulua热更新提高 <三> 网络通信和ProtocolBuffer

原创 说实话,ProtocolBuffer这个东西以前一直在用,很多公司在用,但是怎么配置怎么写还真的研究的少。找了网上很多教程,在ULUA里怎么用,很少有讲到的。首先,分析一下,既然要热更新,那...
  • u012322710
  • u012322710
  • 2016年12月01日 21:23
  • 2176

在LUA中收发网络数据

添加捕鱼网络通讯协议的C++LUA交互接口;用UltraEdit另存为DOS换行符、utf-8无BOM格式,CCLuaLog打印提示最好用英文。 调试时注意点: 1.将框架最新编译的ClientS...
  • u010401391
  • u010401391
  • 2013年05月20日 12:11
  • 2047

利用Wireshark加Lua分析专有网络协议

实战过程: 1.安装wireshark、lua。 2.利用lua为wirashark写一个协议的dissector,并部署到lua上。   2.1 参照http://wiki.wireshark.or...
  • jiangfuqiang
  • jiangfuqiang
  • 2014年03月15日 19:11
  • 6737

lua序列化函数

此函数用来序列化table function serialze(tbl,filename) print (filename) file=io.open(filename,'w') if f...
  • icyday
  • icyday
  • 2012年10月22日 16:09
  • 773

c++向Lua中传递复杂的结构该如何做?

http://www.zhihu.com/question/32195614 用userdata, 参考 Programming in Lua : 28.1 还可以考虑直接ffi,参考FFI ...
  • mydriverc2
  • mydriverc2
  • 2016年03月29日 14:23
  • 1241

lua里table转string(序列化)和string转table(反序列化)

网上找到的代码,非常完美,出处已经不可查,见谅 function serialize(obj) local lua = "" local t = type(obj) ...
  • Eddids
  • Eddids
  • 2015年04月27日 15:04
  • 4872
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一次序列化与反序列化自有协议的经历(lua版本)
举报原因:
原因补充:

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