SuperSheeps处理常见报文格式

一般来说产品在设计协议时,会制定一定的协议二进制格式,包含协议头和协议正文,协议头包含一些标识信息,协议正文部分则是protobuf、json等承载的业务参数序列化后的字节串。我们在发送消息时要进行正确的参数序列化,接收到消息时首先要处理粘包,进行分包再解析。

1. 协议头使用固定字节数标识消息长度

前m个字节标识长度len,一般为1 、2 、 4 、 8
消息格式:

len(m字节) = n msg(n字节)
-- 序列化
-- m = 1, 使用 string.pack("s1", content)
-- m = 2, 使用 string.pack("s2", content)
-- m = 4, 使用 string.pack("s4", content)
-- m = 8, 使用 string.pack("s8", content) 或者 string.unpack("s", content)
local data = string.pack("s2", "hello world!")
-- 分包解析代码
-- m = 1, 使用 string.unpack("s1", data)
-- m = 2, 使用 string.unpack("s2", data)
-- m = 4, 使用 string.unpack("s4", data)
-- m = 8, 使用 string.unpack("s8", data) 或者 string.unpack("s", data)
local pos = 1
local function RpcUnpack(data)  --接收到的消息可能存在粘包,必须进行分包处理
    while true do
        local ok, msg, pos = pcall(string.unpack, "s2", data, pos)
        if ok then
            --完成一个分包
        else
            break
        end
    end
    data = data:sub(pos)  --余留消息,下次接收的消息需要合并到后面,再分包
end

2. 协议头中间使用固定字节数标识消息长度

m个字节标识长度len,一般为2 、 4 、 8
消息格式:

未知标识x(a字节) len(m字节) = n 未知标识y(b字节) msg(n字节)
-- 序列化
-- m = 1, 使用 string.pack("B", data)
-- m = 2, 使用 string.pack("H", data)
-- m = 4, 使用 string.pack("I", data)
-- m = 8, 使用 string.pack("I8", data)
local msg = "hello world!"
local len = string.pack("I", #msg)
local data = x + len + y + msg
-- m = 1, 使用 string.unpack("B", data)
-- m = 2, 使用 string.unpack("H", data)
-- m = 4, 使用 string.unpack("I", data)
-- m = 8, 使用 string.unpack("I8", data)

local function RpcUnpack(data)
    local data_len = #data
    local head_len = a + m + b
    local pos = 1
    while true do
        if data_len < pos + head_len - 1 then
            break  --data not enough
        end
        local len, pos = string.unpack("I", data, pos + a)
        pos = pos + b
        if data_len < pos + len - 1 then
            break   --data not enough
        end
        local msg = data:sub(pos, len)
        --完成一个分包
        pos = pos + len
    end
end

3. 其他协议格式

还有其他各种各样的协议格式,如http的明文协议,websocket中使用变长的字计数标识正文长度,并且对正文进行掩码处理等等,使用时应当根据自身项目的设计细节再进行代码编写。

SuperSheeps处理常见报文格式