--这部分代码用于网络消息的解析和封包
local http = require "http_plugin.http"
local ws = require 'http_plugin.websocket'
--websocket握手阶段,使用http协议
--解析用例消息
local ret, req = http.request_decode(data)
--打包协议,将协议序列化为二进制
local data = http.request_encode(req)
--解析服务器消息,此处不掩饰粘包处理
local ret, res = http.response_decode(data)
--握手完成,使用websocket协议
--解析用例或者服务器消息,此处不演示粘包处理
local content, fin, opcode, encoded_bak, mask, len = ws.decode(data)
--打包协议,将协议序列化为二进制
local data = ws.encode(content, opcode, mask, fin)
local json = require "JSON"
--解析用例或者服务器消息
local obj = json:decode(data)
--打包协议,将协议序列化为二进制
local str = json:encode(obj)
sproto是云风设计一种rpc协议:https://github.com/cloudwu/sproto
--sheeps.lua
--这部分代码加载协议文件,sheeps.lua是框架默认的一个lua虚拟机初始化脚本
local sprotoloader = require "sprotoloader"
function global_vm_init(projectid)
sprotoloader.register("project/lua/"..projectid.."/proto/C2S.proto", 1)
sprotoloader.register("project/lua/"..projectid.."/proto/S2C.proto", 2)
end
function user_vm_init(projectid)
local SP_C2S = sprotoloader.load(1)
local SP_S2C = sprotoloader.load(2)
C2SHost = SP_C2S:host("Package")
S2CHost = SP_S2C:host("Package")
C2SRequest = S2CHost:attach(SP_C2S)
end
--这部分代码用于网络消息的解析和封包
--解析用例消息,此处不演示粘包处理
local ok, rpctype, name, request, response, ud = pcall(C2SHost.dispatch, C2SHost, data)
--打包协议,将协议序列化为二进制
local data = C2SRequest(name, request, session, ud)
--解析服务器消息,此处不掩饰粘包处理
local ok, rpcType, name, request, response, ud = pcall(S2CHost.dispatch, S2CHost, data)
supersheeps 内置luaprotobuf库:https://github.com/starwing/lua-protobuf
//定义addressbook.proto文件
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 uid = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
repeated int32 test = 5 [packed=true];
extensions 10 to max;
}
message Ext {
extend Person {
optional int32 test = 10;
}
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}
使用命名 protoc -o addressbook.pb addressbook.proto 生成 addressbook.pb,然后:
assert(pb.loadfile "addressbook.pb") -- 载入刚才编译的pb文件
local person = { -- 我们定义一个addressbook里的 Person 消息
name = "Alice",
id = 12345,
phone = {
{ number = "1301234567" },
{ number = "87654321", type = "WORK" },
}
}
-- 序列化成二进制数据
local data = assert(pb.encode("tutorial.Person", person))
-- 从二进制数据解析出实际消息
local msg = assert(pb.decode("tutorial.Person", data))
supersheeps内置KCP协议的支持,但是使用kcp的项目通过socks5代理录制的用例消息种会带有kcp协议头,在业务层需要去除。了解KCP:https://github.com/skywind3000/kcp
--解析kcp用例消息
local KcpSn = -1
local function KcpSendMsgUnpack(data)
-- kcp协议头24个字节,判断长度是否足够
local data_len = #data
if data_len < 24 then
return
end
local pos = 1
local len = 0
while pos < data_len do
local sn, npos = string.unpack("I", data, pos + 12)
len, pos = string.unpack("I", data, pos + 20)
--通过 len > 0 过滤控制帧, 通过 sn > KcpSn 过滤重发的帧
if len > 0 and sn > KcpSn then
KcpSn = sn
--conent为业务层需要的数据
local content = string.sub(data, pos, pos + len - 1)
end
pos = pos + len
end
end