skynet.dispatch使用示例详解

作者:

文章目录
  • skynet.dispatch 是 Skynet 框架中用于注册消息处理函数的核心 API。它的作用是为特定类型的消息绑定处理逻辑,当服务收到该类型的消息时,自动调用对应的处理函数。以下是其详细解析:
  • skynet.dispatch(type, func) type:消息类型(字符串或数字)。 常见类型: "lua":默认的 Lua 消息协议(对应 skynet.PTYPE_LUA)。 "socket":网络消息(对应 skynet.PTYPE_SOCKET)。 自定义类型:通过 skynet.register_protocol 注册的协议类型。 func:消息处理函数,格式为 function(session, source, …)。 session:会话 ID,用于响应消息(如 skynet.ret)。 source:发送方服务的地址(skynet.address 格式)。 …:消息内容(由协议定义的解包逻辑生成)。
  • 当服务收到一条消息时,Skynet 会执行以下步骤: 协议匹配:根据消息类型(如 "lua")找到对应的解包函数。 消息解包:调用协议注册的 unpack 函数,将二进制数据解析为 Lua 值。 分发处理:调用 skynet.dispatch 注册的处理函数,传入 session、source 和解包后的数据。 协程调度:处理函数在一个独立的协程中执行,避免阻塞其他消息处理。
  • 协议注册:定义如何解析和打包消息。 skynet.register_protocol { name = “binary”, id = skynet.PTYPE_USER, — 自定义 ID unpack = function(msg, sz) return msg, sz end, — 不解包,直接传递原始数据 pack = skynet.pack — 默认打包函数 } 消息分发:通过 skynet.dispatch 绑定处理逻辑。 skynet.dispatch(“binary”, function(session, source, msg, sz) — 处理二进制数据 end)
  • 避免阻塞主线程:若处理函数中有耗时操作(如大量计算、同步 IO),应使用 skynet.fork 创建新协程。 skynet.dispatch(“lua”, function(session, source, cmd) if cmd == “heavy_task” then skynet.fork(function() — 在子协程中执行耗时操作 local result = heavy_compute() skynet.ret(skynet.pack(result)) end) end end) 协程生命周期:确保每个协程最终退出,避免内存泄漏(如通过 pcall 捕获异常)。 线程安全:Skynet 服务是单线程的,但协程间共享 Lua 虚拟机状态,需谨慎处理共享数据(推荐使用 skynet.sharedata)。
  • RPC 调用:处理远程服务请求并返回结果。 网络消息:解析 TCP/UDP 数据包,如游戏协议、HTTP 请求。 定时任务:通过 skynet.timeout 触发延时逻辑。
  • skynet.dispatch 是 Skynet 服务的消息处理入口,通过绑定协议类型与处理函数,实现灵活的消息分发机制。理解其协程调度、协议注册和响应机制,是构建高效 Skynet 服务的关键。结合 sproto 等协议工具,可以进一步简化网络通信的复杂性。 到此这篇关于skynet.dispatch 使用示例详解的文章就介绍到这了,更多相关skynet.dispatch 使用内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
  • 目录
    • skynet.dispatch 函数详解
    • 1. 函数定义与参数
    • 2. 消息处理流程
    • 3. 使用示例
      • 示例 1:处理 Lua 协议消息
      • 示例 2:处理自定义协议消息
    • 4. 关键机制
      • (1) 协程与阻塞操作
      • (2) 消息响应
    • 5. 与 skynet.register_protocol 的协作
      • 6. 注意事项
        • 7. 典型应用场景
          • 总结

            skynet.dispatch 是 Skynet 框架中用于注册消息处理函数的核心 API。它的作用是为特定类型的消息绑定处理逻辑,当服务收到该类型的消息时,自动调用对应的处理函数。以下是其详细解析:

            skynet.dispatch(type, func)
            • type:消息类型(字符串或数字)。
              • 常见类型:
                • "lua":默认的 Lua 消息协议(对应 skynet.PTYPE_LUA)。
                • "socket":网络消息(对应 skynet.PTYPE_SOCKET)。
                • 自定义类型:通过 skynet.register_protocol 注册的协议类型。
            • func:消息处理函数,格式为 function(session, source, ...)
              • session:会话 ID,用于响应消息(如 skynet.ret)。
              • source:发送方服务的地址(skynet.address 格式)。
              • ...:消息内容(由协议定义的解包逻辑生成)。

            当服务收到一条消息时,Skynet 会执行以下步骤:

            • 协议匹配:根据消息类型(如 "lua")找到对应的解包函数。
            • 消息解包:调用协议注册的 unpack 函数,将二进制数据解析为 Lua 值。
            • 分发处理:调用 skynet.dispatch 注册的处理函数,传入 sessionsource 和解包后的数据。
            • 协程调度:处理函数在一个独立的协程中执行,避免阻塞其他消息处理。

            local skynet = require "skynet"
            -- 注册 Lua 类型消息的处理函数
            skynet.dispatch("lua", function(session, source, cmd, ...)
                if cmd == "add" then
                    local a, b = ...
                    skynet.ret(skynet.pack(a + b))
                elseif cmd == "ping" then
                    skynet.ret(skynet.pack("pong"))
                end
            end)
            skynet.start(function()
                -- 服务初始化代码
            end)

            说明

            • 当收到 "lua" 类型的消息时,解析出命令 cmd 和参数。
            • 根据 cmd 执行逻辑,并通过 skynet.ret 返回结果。

            local skynet = require "skynet"
            -- 注册自定义协议
            skynet.register_protocol {
                name = "myproto",
                id = 100,  -- 自定义协议 ID(需唯一)
                unpack = function(msg, sz)
                    -- 自定义解包逻辑(如 sproto 解析)
                    return myproto.decode(msg, sz)
                end
            }
            -- 处理自定义协议消息
            skynet.dispatch("myproto", function(session, source, data)
                print("Received:", data)
                skynet.ret()  -- 无返回值
            end)
            skynet.start(function()
                -- 服务初始化代码
            end)
            • 自定义协议需要先通过 skynet.register_protocol 注册。
            • 收到类型为 "myproto" 的消息时,调用自定义解包函数,并处理数据。

            • 协程调度:每条消息的处理在独立协程中执行,互不阻塞。
            • 阻塞 API:若处理函数中调用 skynet.callskynet.sleep 等阻塞 API,当前协程会被挂起,直到操作完成。
            skynet.dispatch("lua", function(session, source, cmd)
                if cmd == "slow_task" then
                    skynet.sleep(100)  -- 挂起协程 1 秒
                    skynet.ret("Done")
                end
            end)

            • skynet.ret:用于向发送方返回响应。
              • 若消息是请求(skynet.call),必须调用 skynet.ret
              • 若消息是通知(skynet.send),无需返回。
            skynet.dispatch("lua", function(session, source, cmd)
                if session ~= 0 then  -- 需要响应
                    skynet.ret(skynet.pack("Response"))
                end
            end)

            协议注册:定义如何解析和打包消息。

            skynet.register_protocol {
                name = "binary",
                id = skynet.PTYPE_USER,  -- 自定义 ID
                unpack = function(msg, sz) return msg, sz end,  -- 不解包,直接传递原始数据
                pack = skynet.pack  -- 默认打包函数
            }

            消息分发:通过 skynet.dispatch 绑定处理逻辑。

            skynet.dispatch("binary", function(session, source, msg, sz)
                -- 处理二进制数据
            end)

            避免阻塞主线程
            若处理函数中有耗时操作(如大量计算、同步 IO),应使用 skynet.fork 创建新协程。

            skynet.dispatch("lua", function(session, source, cmd)
                if cmd == "heavy_task" then
                    skynet.fork(function()
                        -- 在子协程中执行耗时操作
                        local result = heavy_compute()
                        skynet.ret(skynet.pack(result))
                    end)
                end
            end)

            协程生命周期
            确保每个协程最终退出,避免内存泄漏(如通过 pcall 捕获异常)。

            线程安全
            Skynet 服务是单线程的,但协程间共享 Lua 虚拟机状态,需谨慎处理共享数据(推荐使用 skynet.sharedata)。

            • RPC 调用:处理远程服务请求并返回结果。
            • 网络消息:解析 TCP/UDP 数据包,如游戏协议、HTTP 请求。
            • 定时任务:通过 skynet.timeout 触发延时逻辑。

            skynet.dispatch 是 Skynet 服务的消息处理入口,通过绑定协议类型与处理函数,实现灵活的消息分发机制。理解其协程调度、协议注册和响应机制,是构建高效 Skynet 服务的关键。结合 sproto 等协议工具,可以进一步简化网络通信的复杂性。

            到此这篇关于skynet.dispatch 使用示例详解的文章就介绍到这了,更多相关skynet.dispatch 使用内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

            站内搜索