下面给你整理一份 《Skynet dispatch 使用示例详解(超全)》,从概念、原理到实战示例,让你彻底弄懂服务端消息处理的核心机制。
一、skynet.dispatch 是什么?
在 Skynet 框架中,所有 服务之间的消息通信,都依赖于 dispatch 来处理:
- 作用:注册消息处理函数,决定服务收到消息后如何处理
- 典型用法:
skynet.dispatch("lua", function(session, source, cmd, ...)
-- 处理消息逻辑
end)
- 第一个参数:消息类型(常用
"lua"、"text"等) - 第二个参数:回调函数,参数通常是:
session:会话 ID,用于返回结果source:发送消息的服务地址...:消息内容(由发送方传递)
二、dispatch 参数详解
skynet.dispatch(proto, func)
| 参数 | 说明 |
|---|---|
| proto | 消息类型,例如 "lua"、"text"、自定义协议 |
| func | 回调函数,形式:function(session, source, ...) |
- session = 0:表示消息是单向的(send 发送)
- session > 0:表示消息可回复(call / rawcall)
三、dispatch 使用场景
- 处理普通 RPC 请求
- 处理异步消息 / 通知
- 自定义协议消息
- 内部服务通信
四、dispatch 基本示例
服务端 user.lua
local skynet = require "skynet"
local CMD = {}
function CMD.getName(uid)
return "User_" .. uid
end
function CMD.add(a, b)
return a + b
end
-- 注册消息处理
skynet.start(function()
skynet.dispatch("lua", function(session, source, cmd, ...)
local f = CMD[cmd]
if f then
skynet.ret(skynet.pack(f(...))) -- 返回结果给调用方
else
skynet.error("Unknown command:", cmd)
end
end)
end)
客户端调用
local skynet = require "skynet"
local name = skynet.call(".user", "lua", "getName", 1001)
print(name) -- 输出:User_1001
local sum = skynet.call(".user", "lua", "add", 10, 20)
print(sum) -- 输出:30
- 核心:dispatch 注册了
"lua"类型的消息处理 - call 自动挂起协程,dispatch 返回结果后协程恢复
五、dispatch 异步消息示例
- 使用
skynet.send发送通知 - session = 0,不需要返回值
客户端发送
skynet.send(".user", "lua", "notify", "Hello World")
服务端 dispatch
skynet.dispatch("lua", function(session, source, cmd, msg)
if cmd == "notify" then
skynet.info("Received message:", msg)
end
-- session = 0,不返回
end)
特点:
- 异步消息不会阻塞调用方
- dispatch 可以同时处理多种消息类型
六、dispatch 多协议示例
-- 处理 lua 消息
skynet.dispatch("lua", function(session, source, cmd, ...)
print("Lua message:", cmd, ...)
end)
-- 处理 text 消息
skynet.dispatch("text", function(session, source, msg)
print("Text message:", msg)
end)
- 适用于服务同时处理 RPC、日志通知、文本命令等
七、dispatch + rawcall 示例
skynet.dispatch("lua", function(session, source, cmd, ...)
if cmd == "getName" then
local reply = "User_" .. ...
skynet.ret(skynet.pack(reply)) -- 可用于 rawcall 或 call
end
end)
- rawcall 发送消息时也会被 dispatch 拦截
- 手动处理返回值
八、dispatch 高级用法
1. 使用 CMD 表集中管理命令
local CMD = {}
function CMD.hello()
return "Hello Skynet"
end
function CMD.add(a, b)
return a + b
end
skynet.dispatch("lua", function(session, source, cmd, ...)
local f = CMD[cmd]
if f then
skynet.ret(skynet.pack(f(...)))
else
skynet.error("Unknown cmd:", cmd)
end
end)
2. 防止并发冲突
- 对于需要顺序执行的操作,可以使用
skynet.queue:
local skynet = require "skynet"
local queue = require "skynet.queue"
local q = queue()
skynet.dispatch("lua", function(session, source, cmd, ...)
q(function()
-- 顺序处理 cmd
skynet.ret(skynet.pack(CMD[cmd](...)))
end)
end)
九、dispatch 注意事项
- session 管理
- call / rawcall 消息的 session > 0
- send 消息 session = 0,不返回
- 返回值处理
- 必须使用
skynet.ret(skynet.pack(...))返回结果
- 必须使用
- 并发处理
- 默认 dispatch 是并发处理的
- 对共享资源操作建议用 skynet.queue 或自定义锁
- 多协议共存
- 可以同时注册
"lua"、"text"等多种协议
- 可以同时注册
- 错误捕获
- dispatch 内部异常不会影响 Skynet 框架,但会打印日志
十、dispatch 核心总结
- 作用:注册消息处理函数,是 Skynet 服务端处理消息的核心
- 用法:
skynet.dispatch(proto, func) - 关键点:
- proto 对应消息类型
- func 参数
(session, source, ...) - call 消息需要
skynet.ret返回 - send 消息 session = 0,无返回
- 典型场景:
- RPC 请求处理(call / rawcall)
- 异步通知处理(send)
- 日志、心跳、状态同步等内部通信