在前面的文章:skynet:session 中,已经使用过 skynet.ret / skynet.retpack 对消息进行应答。但这两个函数有一个使用限制,即:消息接收与消息应答必须在同一个协程里完成,也就是说:请求被哪一个协程接收,就必须在这个协程响应。
这是因为在 skynet 中,当一个服务收到一个消息的时候,会启动一个协程来处理,并把协程句柄与发送消息的服务地址进行一一对应记录在 table 中。当需要响应时,就使用当前调用 skynet.ret / skynet.retpack 的协程句柄去 table 中查询对应的服务地址,然后把消息发给这个服务地址。
若在其他协程中调用 skynet.ret / skynet.retpack,那么就会使用该协程句柄去查询服务地址,最后肯定是查不到的。
解决方法:response 可实现接受请求与响应请求在不同协程中完成。
一、echoluamsg.lua
修改前一篇文章:skynet:session 中的 echoluamsg.lua,testforkcall.lua 与 main.lua 保持不变。
skynet = require "skynet"
require "skynet.manager"
skynet.start(function()
skynet.register("echoluamsg")
skynet.dispatch("lua", function(session, address, msg)
--先把发送服务地址以及session打包到闭包中,可以在任意地方调用
local response = skynet.response(skynet.pack)--指定打包函数
skynet.fork(function(msg)--开启一个新的协程来处理响应
skynet.sleep(500)
skynet.error("recv " .. msg)
response(true, msg:upper())--第一个参数true表示应答成功,false则应答错误消息
end, msg)
end)
end)
-
local response = skynet.response(pack)
- pack:响应消息打包函数,默认为 skynet.pack;
- 返回值:一个闭包函数。
-
response(ok, …)
参数 ok 的值可以是:- “test”:检查接收响应的服务是否存在;
- true:发送应答 PTYPE_RESPONSE;
- false:发送 PTYPE_ERROR 错误消息。
二、测试结果
版权声明:本文为u010601662原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。