skynet:自帶網關服務

一、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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章