记一次学习skynet中的C/Lua接口编程解析protobuf过程
1.引言
最近在学习skynet过程中发现在网络收发数据的过程中数据都是裸奔,就想加入一种数据序列化方式,json、xml简单好用,但我就是不想用,于是就想到了protobuf,对于protobuf C/C++的使用个人感觉有点重,正好在学Lua,就想着能不能通过Lua来处理这些业务逻辑,C/C++只负责底层功能,最开始是想自己通过C实现一个动态库给Lua调用,但是后来估算了一下工作量,怕自己走火入魔果断放弃,于是就去github寻找灵感,于是找到了lua-protobuf,OK有轮子了,不想再造了,直接用。
2.组织工程
现在来到第一步,创建echo工程。
mkdir echo && cd echo
第二步:拉取skynet项目到工作目录并构建。
git clone https://github.com/cloudwu/skynet.git
cd skynet
git submodule init
git submodule update
make PLAT=linux
第三步:拉取lua-protobuf到工作目录并构建。
git clone https://github.com/starwing/lua-protobuf.git
cd lua-protobuf
mkdir build && cd build
cmake ..
make
最后,这是我的现有工程结构,如下图。
OK,准备工作已经完毕,开始炼丹...
3.无内鬼可以炼丹
所有自己的Lua代码都会放在lua -src目录,现在基于skynet创建一个echo服务,代码如下
-- main.lua
local skynet = require "skynet"
local socket = require "skynet.socket"
local pb = require "pb"
local serpent = require "serpent"
local function load_proto_file(filepath)
pb.loadfile(filepath)
end
local function sendto(clientfd, arg)
socket.write(clientfd, arg)
end
local function client_quit(clientfd)
socket.close(clientfd)
end
local function accept(clientfd, addr)
socket.start(clientfd)
local data = socket.read(clientfd)
if not data then
client_quit(clientfd)
return
end
local res = {
token = "aaaaaaaaa"
}
-- 解码接收到的数据
local dedata = pb.decode("Login.LoginRequest", data)
print("recv : ", serpent.block(dedata))
-- 将lua原表编码成protobuf的二进制数据
local tmp = pb.encode("Login.LoginResponse", res)
print("send : ", serpent.block(tmp))
sendto(clientfd, tmp)
socket.close(clientfd)
end
local function main()
-- 为了简单直接绝对路径写死
load_proto_file("/home/oyj/game/echo/Login.pb")
local listenfd = socket.listen("0.0.0.0", 8888)
socket.start(listenfd, accept)
end
skynet.start(main)
代码写完,开始写配置文件,在项目根目录写一个配置文件,如下:
thread=4
logger=nil
harbor=0
start="main"
-- 这里吧lua-protobuf的Lua文件路径告诉skynet
lua_path="./skynet/lualib/?.lua;./skynet/lualib/?/init.lua;./lualib/?.lua;./lua-protobuf/?.lua"
-- 我们下的lua代码在这里配置加载路径
luaservice="./skynet/service/?.lua;./lua-src/?.lua;"
lualoader="./skynet/lualib/loader.lua"
-- 配置lua-protobuf动态库的路径,让skynet可以加载到动态库
cpath="./skynet/cservice/?.so;./lua-protobuf/build/?.so"
lua_cpath="./skynet/luaclib/?.so;./lua-protobuf/build/?.so"
再写一个proto文件:
// Login.proto
syntax = "proto3";
package Login;
message LoginRequest {
string username = 1;
string password = 2;
}
message LoginResponse {
string token = 1;
}
最后将proto文件生成Lua要的pb文件。
protoc -I . -o Login.pb Login.proto
最后找个之前客户端来测试,整体代码太多就不全部贴出来了,相信能看到这你是有点东西的,自己写应该简简单单,大概代码如下:
最最后目前的项目结构:
4.开始试丹
丹成!!!命令行进入工程根目录运行一下命令开始试丹!
./skynet/skynet config
skynet启动成功,效果如下:
发个数据测试一下:
client:
server:
OK,丹没毒放心食用