网络消息的处理流程
网络消息的监听:由socketdrive.strat(socket)负责监听网络消息
/home/mogu/skynet/skynet/lualib/snax/gateserver.lua ,在此文件中调用。
function CMD.open( source, conf )
assert(not socket)
local address = conf.address or "0.0.0.0"
local port = assert(conf.port)
maxclient = conf.maxclient or 1024
nodelay = conf.nodelay
skynet.error(string.format("Listen on %s:%d", address, port))
socket = socketdriver.listen(address, port)
**socketdriver.start**(socket)
if handler.open then
return handler.open(source, conf)
end
end
收到客户端的消息的处理
1)在gavaserver中,已经定义了网络消息的处理流程
local function dispatch_msg(fd, msg, sz)
if connection[fd] then
handler.message(fd, msg, sz)
else
skynet.error(string.format("Drop message from fd (%d) : %s", fd, netpack.tostring(msg,sz)))
end
end
MSG.data = dispatch_msg
skynet.register_protocol {
name = "socket",
id = skynet.PTYPE_SOCKET, -- PTYPE_SOCKET = 6
unpack = function ( msg, sz )
return netpack.filter( queue, msg, sz)
end,
dispatch = function (_, _, q, type, ...)
queue = q
print("-=-== type = ", data)
-- if type == 'more' then assert(false) end
if type then
MSG[type](...)
end
end
}
2)在dispatch_msg中调用了handler.message,对消息进行派发。handler.message函数,有gate定义
function handler.message(fd, msg, sz)
-- recv a package, forward it
local c = connection[fd]
local agent = c.agent -- 由agent服务启动的时候,调用CMD.forward传入。
if agent then
skynet.redirect(agent, c.client, "client", 1, msg, sz)
else
skynet.send(watchdog, "lua", "socket", "data", fd, netpack.tostring(msg, sz))
end
end
3)详细看看,c.agent的的来源。c.agent由watchdog中的SOCKET.open中启动agent服务时候传入。
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
4)再看下SOCKET.open的调用者,是由gate中handler.connert调用
function handler.connect(fd, addr)
local c = {
fd = fd,
ip = addr,
}
connection[fd] = c
skynet.send(watchdog, "lua", "socket", "open", fd, addr)
end
5)handler.connect的调用者,是前面提到的gateserver服务中的MSG.open
function MSG.open(fd, msg)
if client_number >= maxclient then
socketdriver.close(fd)
return
end
if nodelay then
socketdriver.nodelay(fd)
end
connection[fd] = true
client_number = client_number + 1
handler.connect(fd, msg)
end
最后有很多的问题都指向了gateserver中skynet.register_protocol协议注册。是哪里调用了dispatch。
这个时候,我们可以看看skynet.lua中对skynet.register_protocol的定义。
function skynet.dispatch_message(...)
local succ, err = pcall(raw_dispatch_message,...)
while true do
local key,co = next(fork_queue)
if co == nil then
break
end
fork_queue[key] = nil
local fork_succ, fork_err = pcall(suspend,co,coroutine_resume(co))
if not fork_succ then
if succ then
succ = false
err = tostring(fork_err)
else
err = tostring(err) .. "\n" .. tostring(fork_err)
end
end
end
assert(succ, tostring(err))
end
local debug = require "skynet.debug"
debug.init(skynet, {
dispatch = skynet.dispatch_message,
suspend = suspend,
})
skynet.dispatch()这个函数的使用相信小伙伴们都比较熟悉了吧,在skynet中,服务消息的派发都是依靠这个函数的。到了这里,我也很迷糊。。没有搞清楚。