sproto

sproto是一套由skynet自身提供的協議,類似google protobuffers,但設計更簡單,也更利於lua使用,同時還提供了一套簡單的rpc方案.


RPC

需要一個消息包的主體格式,它必須有一個叫type的字段,描述RPC到底是哪一條消息,還要有一個session字段來表示迴應消息的對應關係,通常這兩個字段都被定義成integer.

.package {
    type 0 : integer
    session 1 : integer
}
使用sproto的rpc框架,每條消息都會以這條消息開頭,接上真正的消息內容;連接在一起後用sproto的0-pack方式打包,這個數據包並不包含長度信息,所以真正在網絡上傳輸,還需要添加長度信息,方便分包,如果使用skynet的gate模塊的話,約定了以兩字節大端表示的長度加內容的方式分包.


構造一個sproto rpc 的消息處理器,應使用:

local host = sproto:host(packagename)  -- packagename 默認值爲 "package" 即對應前面的 .package 類型。你也可以起別的名字。
這條調用會返回一個host對象,用於處理接受的消息.
host:dispatch(msgcontent)
上面這條代碼用於處理一條信息.這裏的msgcontent 也是一個字符串,或是一個userdata(指針)加一個長度.它應符合上述的以sproto的0-pack方式打包的包格式.
dispatch 調用有兩種可能的返回類別,由第一個返回值決定:
REQUEST:第一個返回值爲"REQUEST"時,表示這是一個遠程請求,如果請求包中沒有session字段,表示該請求不需要回應,這時,第2和第3個返回值分別爲消息類型名(即在sproto定義中提到的某個以.開頭的類型名),以及消息內容(通常是一個table);如果請求包中有session字段,那麼還會有第4個返回值:一個用於生產迴應包的函數.
RESPONSE:第一個返回值爲"RESPONSE"時,第2和第3個返回值分別爲session和消息內容,消息內容通常是一個table,但也可能不存在內容(僅僅是一個迴應確認).
local sender = host:attach(sp)  -- 這裏的 sp 指向外發出的消息協議定義。
attach可以構造一個發送函數,用來將對外請求打包編碼成可以被dispatch正確解碼的數據包.
這個sender函數接受三個參數(name,args,session).name是消息的字符串名,args是一張保存用消息內容的table,而session是你提供的唯一識別號,用於讓對方正確的迴應,當比的協議不規定要回應時,session可以不給出,同樣,args也可以爲空.
Sproto Loader

由於 skynet 採用的是多 lua 虛擬機。如果在每個 VM 裏都加載相同的 sproto 協議定義就略顯浪費。所以 skynet 還提供了一個叫 sprotoloader 的模塊來共享它們。

其實現原理是在 C 模塊中提供了 16 個全局的 slot ,可以通過 sprotoloader.register 或 sprotoloader.save 在初始化時,加載需要的協議,並保存在這些 slot 裏。通常我們只需要兩個 slot ,一個用於保存客戶端到服務器的協議組,另一個用於保存服務器到客戶端的協議組。分別位於 slot 1 和 2 。

這樣,在每個 vm 內,都可以通過 sprotoloader.load 把協議加載到 vm 中。

注意:這套 api 並非線程安全。所以必須自行保證在初始化完畢後再做 load 操作。(load 本身是線程安全的)。


具體的使用範例,可以參考 examples 下的 agent.lua 以及 examples 下的 client.lua 。理解 RPC 是如何工作的

發佈了35 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章