服務消息分發和迴應
同樣在同一個目錄建立3個文件(config,main.lua,service2.lua)
config文件參考上一節
main.lua代碼:
local skynet = require "skynet"
-- 啓動服務(啓動函數)
skynet.start(function()
-- 啓動函數裏調用Skynet API開發各種服務
print("======Server start=======")
-- skynet.newservice(name, ...)啓動一個新的 Lua 服務(服務腳本文件名)
local service2 = skynet.newservice("service2")
-- 向service2服務發出請求,設置key1的值
skynet.call(service2,"lua","set","key1","value111111")
-- 向service2服務發出請求,獲取key1的值
local kv = skynet.call(service2,"lua","get","key1")
print(kv)
-- 退出當前的服務
skynet.exit()
end)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
skynet.send(address, typename, …) 把一條類別爲 typename 的消息發送給 address 。它會先經過事先註冊的 pack 函數打包 … 的內容。
skynet.send 是一條非阻塞 API ,發送完消息後,coroutine 會繼續向下運行,這期間服務不會重入。
skynet.call(address, typename, …) 這條 API 則不同,它會在內部生成一個唯一 session ,並向 address 提起請求,並阻塞等待對 session 的迴應(可以不由 address 迴應)。當消息迴應後,還會通過之前註冊的 unpack 函數解包。
尤其需要留意的是,skynet.call 僅僅阻塞住當前的 coroutine ,而沒有阻塞整個服務。在等待迴應期間,服務照樣可以響應其他請求。所以,尤其要注意,在 skynet.call 之前獲得的服務內的狀態,到返回後,很有可能改變。
service2.lua代碼:
-- 每個服務獨立, 都需要引入skynet
local skynet = require "skynet"
require "skynet.manager" -- 引入 skynet.register
local db = {}
local command = {}
function command.get(key)
print("comman.get:"..key)
return db[key]
end
function command.set(key, value)
print("comman.set:key="..key..",value:"..value)
db[key] = value
local last = db[key]
return last
end
skynet.start(function()
print("==========Service2 Start=========")
skynet.dispatch("lua", function(session, address, cmd, ...)
print("==========Service2 dispatch============"..cmd)
local f = command[cmd]
if f then
-- 迴應一個消息可以使用 skynet.ret(message, size) 。
-- 它會將 message size 對應的消息附上當前消息的 session ,以及 skynet.PTYPE_RESPONSE 這個類別,發送給當前消息的來源 source
skynet.ret(skynet.pack(f(...))) --迴應消息
else
error(string.format("Unknown command %s", tostring(cmd)))
end
end)
--可以爲自己註冊一個別名。(別名必須在 32 個字符以內)
skynet.register "SERVICE2"
end)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
迴應一個消息可以使用 skynet.ret(message, size) 。它會將 message size 對應的消息附上當前消息的 session ,以及 skynet.PTYPE_RESPONSE 這個類別,發送給當前消息的來源 source 。
由於某些歷史原因(早期的 skynet 默認消息類別是文本,而沒有經過特殊編碼),這個 API 被設計成傳遞一個 C 指針和長度,而不是經過當前消息的 pack 函數打包。或者你也可以省略 size 而傳入一個字符串。
由於 skynet 中最常用的消息類別是 lua ,這種消息是經過 skynet.pack 打包的,所以慣用法是 skynet.ret(skynet.pack(…)) 。
skynet.pack(…) 返回一個 lightuserdata 和一個長度,符合 skynet.ret 的參數需求;與之對應的是 skynet.unpack(message, size) 它可以把一個 C 指針加長度的消息解碼成一組 Lua 對象。
運行程序:
./skynet ./myexample/e1/config
- 1
- 2