在skynet.start里写skynet.dispatch有啥用?
有些地方的skynet.register_protocol,那又是干啥用的?
一脸懵逼啊
懵逼? 不用懵逼,下面我来捋一捋
关于typename叫做"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)
这是skynet源码中,example里watchdog的一个代码片段.
当有人用skynet.send(addr, "lua"
, ...)或者skynet.call(addr, "lua"
, ...)之类的方法呼叫, skynet就会用skynet.dispatch("lua"
, func)里的func来处理.
上面send/call/dispatch里的"lua"
就是typename,也就是skynet里proto[typename
]的key
,这样讲你可能有点晕,那么放一段代码
function skynet.send(addr, typename, ...)
local p = proto[typename]
return c.send(addr, p.id, 0 , p.pack(...))
end
上面这段是skynet里send的源码, 可以看到通过typename
从proto这个table里去找东西.
那么这个proto是在哪里赋值的呢?来看两段代码:
local REG = skynet.register_protocol
REG {
name = "lua",
id = skynet.PTYPE_LUA,
pack = skynet.pack,
unpack = skynet.unpack,
}
function skynet.register_protocol(class)
local name = class.name
local id = class.id
assert(proto[name] == nil and proto[id] == nil)
assert(type(name) == "string" and type(id) == "number" and id >=0 and id <=255)
proto[name] = class -- 用name注册
proto[id] = class -- 用id注册
end
第一段是注册,第二段是注册的实现.
可以看到skynet在初始化的时候,就注册了proto的key
是lua
的操作了, 但没有dispath的实现, 那么这就需要在服务启动或启动后的某个时刻注册一下.放在skynet.start里进行注册是个不错的时机.
所以就有下面的操作
skynet.start(function()
skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)
-- 一些操作
end)
-- 一些操作
end)
那么如果我不想用"lua"
作为key
可以吗? 当然可以.
自定义typename,注册及实现消息分发
自定义typename
和skynet在初始化里定义有个叫"lua"
的typename是一样的.
下面我直接给两份代码:
local skynet = require "skynet"
local my_id = 101
-- 注册消息, 否则要不然发不出去, 因为没有注册过.
skynet.register_protocol {
name = "eat_toufu", -- 自定义的名字
id = my_id, -- 不要重复使用skynet已经使用的,以防万一(1~12都已经被使用了)
pack = skynet.pack, --可以使用各种各样的pack方法, 这里使用skynet的方案, 不定义的话,就发不出去了.
-- unpack = skynet.unpack, -- 如果不接收的话, 不写也可以
-- dispatch = function() end -- 如果不接收的话, 不写也可以
}
skynet.start(function ()
local myserver= skynet.newservice("myserver")
skynet.send(myserver,"eat_toufu","toufu","delicious") -- 这里使用了自定义的typename [eat_toufu]
skynet.exit()
end)
local skynet = require "skynet"
local my_id = 101
skynet.register_protocol {
name = "eat_toufu",-- 自定义的名字
id = my_id ,
-- pack = skynet.pack, -- 如果不发送的话, 不写也可以
unpack = skynet.unpack, --可以使用各种各样的unpack方法, 这里使用skynet的方案, 不定义的话,就收不到了.
dispatch = function (fd, from, type, ...) --这就是接收的地方.
skynet.error("--->",fd, from, type,...)
end
}
skynet.start(function() end)
第一段代码是发送方, 第二段是接收处理方.
主要就是在register_protocol里的dispatch实现.
这里的dispatch和skynet.dispatch是类似的,结果都是在告诉skynet,针对对应的消息,我要注册一个响应的方法去处理,不同之处在于:
-
skynet.dispatch是针对已经在skynet.register_protocol里注册过的消息名,注册响应方法, 比如
"lua"
. - skynet.register_protocol里的dispatch是在注册新的自定义消息时, 同时实现响应方法.
好了, 要讲的也讲的差不多了, 如果有错的地方, 欢迎指出, 谢谢 :)
网友评论