一、main() 啓動 watchdog
examples/main.lua,會首先啓動一個 watchdog:
local watchdog = skynet.newservice("watchdog")
skynet.call(watchdog, "lua", "start", {
port = 8888,
maxclient = max_client,
nodelay = true,
})
二、watchdog
watchdog 在啓動時,會創建一個網關:
examples/watchdog.lua
skynet.start(function()
skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)
if cmd == "socket" then
local f = SOCKET[subcmd]
f(...)
-- socket api don't need return
else
local f = assert(CMD[cmd])
skynet.ret(skynet.pack(f(subcmd, ...)))
end
end)
gate = skynet.newservice("gate")
end)
watchdog 會接收 main() 傳遞的 lua 消息:start,
function CMD.start(conf)
skynet.call(gate, "lua", "open" , conf)
end
watchdog start() 中會給網關發送 lua 消息:open,通知監聽指定端口。
function CMD.start(conf)
skynet.call(gate, "lua", "open" , conf)
end
三、客戶端連接
3.1、當網關與客戶端建立連接時,會給 watchdog 發送 lua 消息:socket,以爲每一個客戶端連接創建一個 agent 服務:
service/gate.lua
function handler.connect(fd, addr)
local c = {
fd = fd,
ip = addr,
}
connection[fd] = c
skynet.send(watchdog, "lua", "socket", "open", fd, addr)
end
3.2、watchdog 爲每一個客戶端連接創建一個 agent 服務:
examples/watchdog.lua
function SOCKET.open(fd, addr)
skynet.error("New client from : " .. addr)
agent[fd] = skynet.newservice("agent")
skynet.call(agent[fd], "lua", "start", { gate = gate, client = fd, watchdog = skynet.self() })
end
agent 會啓用一個新進程,以 500ms 的速率往客戶端發送心跳包:
examples/agent.lua
function CMD.start(conf)
local fd = conf.client
local gate = conf.gate
WATCHDOG = conf.watchdog
-- slot 1,2 set at main.lua
host = sprotoloader.load(1):host "package"
send_request = host:attach(sprotoloader.load(2))
skynet.fork(function()
while true do
send_package(send_request "heartbeat")
skynet.sleep(500)
end
end)
client_fd = fd
skynet.call(gate, "lua", "forward", fd)
end
四、客戶端連接
gate 會將客戶端數據發送給 watchdog:
service/gate.lua
function handler.message(fd, msg, sz)
-- recv a package, forward it
local c = connection[fd]
local agent = c.agent
if agent then
-- It's safe to redirect msg directly , gateserver framework will not free msg.
skynet.redirect(agent, c.client, "client", fd, msg, sz)
else
skynet.send(watchdog, "lua", "socket", "data", fd, skynet.tostring(msg, sz))
-- skynet.tostring will copy msg to a string, so we must free msg here.
skynet.trash(msg,sz)
end
end