引言:
假如我們要建立的skynet服務器與客戶端的連接方式爲長連接,且選擇了Google的Protobuf來定製我們的網絡協議,那麼,接下來我們要解決的問題就是:如何在skynet框架中使用socket+protobuf。
API
幾個常用的skynet接口:
* 輸出錯誤信息: skynet.error(...)
* 獲取本地服務句柄方式: skynet.localname(...)
* 設置定時器方式: skynet.timeout(...)
* skynet強制退出方式: skyname.abort()
* 服務開始方式: skynet.start(...)
* 服務註銷方式: skynet.exit()
* 發送原始文本消息方式: skynet.core.send(...)
更多skynet.lua的API解析可以參考:skynet API:skynet.lua
protobuf在skynet中使用:
一、 linux 環境安裝protobuf
$ sudo apt-get install protobuf-c-compiler protobuf-compiler
輸入protoc --version
libprotoc 2.5.0
二、安裝protobuf環境,安裝步驟如下:
1. 下載protobuf
protobuf下載頁面 https://github.com/protocolbuffers/protobuf/releases/tag/v2.5.0
在此頁面選擇合適的版本,我選擇的是最新的2.5.0
2. 解壓
tar -zxf protobuf-2.5.0.tar.gz
3. 跳轉到解壓後的目錄
cd protobuf-2.5.0
4. 設置編譯目錄
./configure --prefix=/usr/local/protobuf
/usr/local/protobuf/ 爲自己配置的編譯安裝目錄
5. 安裝
還是在解壓的目錄下進行
make
make check
make install
6. 配置環境變量
sudo vim .bash_profile
7. 添加配置文件
export PROTOBUF=/usr/local/protobuf
export PATH=$PROTOBUF/bin:$PATH
PS: 如果第七步數據保存不了可以先切換到root 用戶進行保存
sudo -i
8. 使配置文件生效
source .bash_profile
9. 測試安裝結果
輸入protoc --version
看到如下結果表示安裝成功:
~ maerfeifei$ protoc --version
libprotoc 3.5.0
二、使用pbc動態proto解析庫
由於protobuf的lua版本的支持存在着部分缺陷,爲了避免踩坑,這裏我們直接使用雲風博客中推薦的pbc動態proto解析庫。
1、資源下載:
下載pbc:跟下載skynet源碼一樣,通過git將pbc的源碼克隆到本地:
$ cd skynet/3rd/
$ git clone https://github.com/cloudwu/pbc.git
Cloning into 'pbc'...
remote: Counting objects: 1156, done.
remote: Total 1156 (delta 0), reused 0 (delta 0), pack-reused 1156
Receiving objects: 100% (1156/1156), 302.95 KiB | 310.00 KiB/s, done.
Resolving deltas: 100% (682/682), done.
Checking connectivity... done.
編譯併合入項目:
2、項目編譯:
可以在pbc根目錄下運行make指令編譯項目:
linsh@ubuntu:/application/pbc$ sudo make
cd build && ar rc libpbc.a ../build/o/context.o ../build/o/varint.o ../build/o/array.o ../build/o/pattern.o ../build/o/register.o ../build/o/proto.o ../build/o/map.o ../build/o/alloc.o ../build/o/rmessage.o ../build/o/wmessage.o ../build/o/bootstrap.o ../build/o/stringpool.o ../build/o/decode.o
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o addressbook ../test/addressbook.c -lpbc
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o pattern ../test/pattern.c -lpbc
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o pbc ../test/pbc.c -lpbc
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o float ../test/float.c -lpbc
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o map ../test/map.c -lpbc
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o test ../test/test.c -lpbc
cd build && gcc -O2 -fPIC -Wall -I.. -L. -o decode ../test/decode.c -lpbc
protoc -obuild/addressbook.pb test/addressbook.proto
protoc -obuild/descriptor.pb test/descriptor.proto
protoc -obuild/float.pb test/float.proto
protoc -obuild/test.pb test/test.proto
3、修改LUADIR
protobuf 需要找到lua5.3的目錄,skynet 本身就包含了lua5.3,所以指定到正確的目錄skynet/3rd/lua
將pbc/binding/lua53/makefile中的LUADIR改爲../../../lua
4、修改CFLAGS
在 pbc/binding/lua53/makefile 的 變量 CFLAGS 中加入 -undefined dynamic_lookup
防止出錯 Undefined symbols for architecture x86_64:,源文件中是沒有這個選項的,雖然在後面的用例中可以正常的執行,但可能這不一定是好的方案。
5、工具編譯:
用終端進入pbc項目pbc/binding/lua53目錄下面編譯出protobuf.so:
cd pbc/binding/lua53
sudo make
linsh@ubuntu:/application/pbc/binding/lua$ sudo make
gcc -O2 -fPIC -Wall -shared -o protobuf.so -I../.. -I/usr/local/src/lua-5.3.0/src -L../../build pbc-lua.c -lpbc
linsh@ubuntu:/application/pbc/binding/lua$ ls
build_ios.sh Makefile parser.lua pbc-lua.c protobuf.lua protobuf.so README.md test2.lua test.lua testparser.lua
可以看到多出了一個protobuf.so輸出文件。
6、整合protobuf.so 和protobuf.lua 到pbc中
編譯成功的話,將protobuf.so放在config文件中lua_cpath項配置的目錄下面,同時將protobuf.lua放在config文件lua_path配置的目錄下,就可以調用protobuf中的庫方法。我當前項目這兩項的配置如下:
lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"
lua_cpath = root .. "luaclib/?.so"
則移動文件命令可以如下:
sudo cp protobuf.so /application/skynet/luaclib
sudo cp protobuf.lua /application/skynet/lualib
三、測試
1、生成proto文件
先在項目根目錄下創建一個protos文件夾,用來存放協議文件,創建一個Person.proto協議文件,內容如下:
sudo mkdir protos
cd protos
sudo vi Person.proto
協議文件的內容如下:
packae cs;
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
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;
}
2、將協議文件導出爲.pb格式:
linsh@ubuntu:/application/skynet/protos$ sudo protoc --descriptor_set_out Person.pb Person.proto
linsh@ubuntu:/application/skynet/protos$ ls
Person.pb Person.proto
目錄下多出了一個對應的.pb文件。
3、使用.pb 文件
在lua中註冊對應的協議文件:
引入protobuf.lua:
local pb = require "protobuf"
註冊.proto協議文件所對應的.pb文件,註冊方法有兩種:
方法一:直接註冊文件:
pb.register_file "Person.pb"
方法二:通過io讀取文件,然後再獲取文本內容進行註冊:
file = io.open("Person.pb","rb")
buffer = file:read "*a"
file:close()
pb.register(buffer)
4、完整用例
通過 encode 和 decode 兩個接口來實現編碼和解碼,完整測試腳本:
local skynet = require "skynet"
local protobuf = require "protobuf"
skynet.start(function()
protobuf.register_file "./protos/Person.pb"
skynet.error("註冊協議文件:Person.pb")
stringbuffer = protobuf.encode("cs.Person",
{
name = "linsh",
id = 1,
})
local data = protobuf.decode("cs.Person",stringbuffer)
skynet.error("數據編碼:name="..data.name..",id="..data.id)
end)
運行正確的結果:
[:0100000c] 註冊協議文件:Person.pb
[:0100000c] 數據編碼:name=linsh,id=1
除外,雲風還自定義了一套協議格式sproto,據說比protobuf還要簡單。
參考:
cocos2dx和skynet通信
lua-protobuf 使用說明
lua pbc
pbc/binding/lua/README.md
skyne use pbc protobuf
---------------------
作者:河樂不爲
來源:CSDN
原文:https://blog.csdn.net/linshuhe1/article/details/70186603
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!