skynet.dispatch 使用详解

目录

  • [skynet.dispatch 函数详解](#skynet.dispatch 函数详解)
    • [1. 函数定义与参数](#1. 函数定义与参数)
    • [2. 消息处理流程](#2. 消息处理流程)
    • [3. 使用示例](#3. 使用示例)
      • [示例 1:处理 Lua 协议消息](#示例 1:处理 Lua 协议消息)
      • [示例 2:处理自定义协议消息](#示例 2:处理自定义协议消息)
    • [4. 关键机制](#4. 关键机制)
      • [(1) 协程与阻塞操作](#(1) 协程与阻塞操作)
      • [(2) 消息响应](#(2) 消息响应)
    • [5. 与 skynet.register_protocol 的协作](#5. 与 skynet.register_protocol 的协作)
    • [6. 注意事项](#6. 注意事项)
    • [7. 典型应用场景](#7. 典型应用场景)
  • 总结

skynet.dispatch 函数详解

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


1. 函数定义与参数

lua 复制代码
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 格式)。
    • ...:消息内容(由协议定义的解包逻辑生成)。

2. 消息处理流程

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

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

3. 使用示例

示例 1:处理 Lua 协议消息

lua 复制代码
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 返回结果。

示例 2:处理自定义协议消息

lua 复制代码
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" 的消息时,调用自定义解包函数,并处理数据。

4. 关键机制

(1) 协程与阻塞操作

  • 协程调度:每条消息的处理在独立协程中执行,互不阻塞。

  • 阻塞 API :若处理函数中调用 skynet.callskynet.sleep 等阻塞 API,当前协程会被挂起,直到操作完成。

    lua 复制代码
    skynet.dispatch("lua", function(session, source, cmd)
        if cmd == "slow_task" then
            skynet.sleep(100)  -- 挂起协程 1 秒
            skynet.ret("Done")
        end
    end)

(2) 消息响应

  • skynet.ret :用于向发送方返回响应。

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

5. 与 skynet.register_protocol 的协作

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

    lua 复制代码
    skynet.register_protocol {
        name = "binary",
        id = skynet.PTYPE_USER,  -- 自定义 ID
        unpack = function(msg, sz) return msg, sz end,  -- 不解包,直接传递原始数据
        pack = skynet.pack  -- 默认打包函数
    }
  • 消息分发 :通过 skynet.dispatch 绑定处理逻辑。

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

6. 注意事项

  1. 避免阻塞主线程

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

    lua 复制代码
    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)
  2. 协程生命周期

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

  3. 线程安全

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


7. 典型应用场景

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

总结

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

相关推荐
慢慢沉19 小时前
Lua(数据库访问)
开发语言·数据库·lua
慢慢沉19 小时前
Lua协同程序(coroutine)
lua
慢慢沉2 天前
Lua元表(Metatable)
lua
慢慢沉2 天前
Lua(字符串)
开发语言·lua
慢慢沉2 天前
Lua(数组)
开发语言·lua
慢慢沉2 天前
Lua(迭代器)
开发语言·lua
慢慢沉2 天前
Lua基本语法
开发语言·lua
Feng.Lee3 天前
接口测试Postman工具高级使用技巧
功能测试·测试工具·lua·postman·可用性测试
三翼鸟数字化技术团队3 天前
鸿蒙平台运行Lua脚本
lua·harmonyos