> 文章列表 > 【从零开始学Skynet】基础篇(三):服务模块常用API

【从零开始学Skynet】基础篇(三):服务模块常用API

【从零开始学Skynet】基础篇(三):服务模块常用API

1、服务模块       

          Skynet提供了开启服务和发送消息的API,必须要先掌握它们。列出了Skynet中8个最重要的API,PingPong程序会用到它们。

Lua API 说明
newservice(name, ...)

启动一个名为 name 的新服务,并返回服务的地址。

start(func)         用 func 函数初始化服务,并将消息处理函数注册到 C 层,让该服务可以工作。
dispatch(type, func) 

        为 type 类型的消息设定一个处理函数。Skynet支持多种消息类型,由于Lua服务间的消息类型是“lua”,因此这里暂时将它定为“lua”。func是指收到消息后的处理函数,当一个服务收到消息时,skynet就会开启新协程,并调用它。       

send(addr, type, ...)

        用 type 类型向 addr 发送一个消息,消息名为cmd。发送方用skynet.send发送消息,接收方用skynet.dispatch接受消息,它们的参数相互对应。若用于服务间通信,类型一般固定为“lua”

call(addr, type, ...) 用 type 类型发送一个消息到 addr ,并等待对方的回应。skynet.call是个阻塞方法。
exit()

结束当前服务。

self() 返回当前服务的地址。
error(msg) 打印日志,向 log 服务发送一条消息。

更多API可以参见:https://github.com/cloudwu/skynet/wiki/APIList

 2、程序开发 

        初看API文档可能一头雾水,结合下面的实例开发才能融会贯通。

        按如下图所示,开启两个ping类型的服务ping1和ping2,让ping1给ping2发消息,ping2收到

后回应ping1,ping1收到再回应ping2,不断循环。

3、代码实现 

(1)主服务

           在skynet/examples目录下新建main_ping.lua文件,输入如下所示代码:

local skynet = require "skynet"
skynet.start(function()skynet.error("[PingMain] start")local ping1 = skynet.newservice("Ping")local ping2 = skynet.newservice("Ping")skynet.send(ping1, "lua", "start", ping2)skynet.exit()
end)
  1. 主服务启动服务后,会先打印“[PingMain]start”的日志输出;
  2. 然后开启两个ping类型的服务,它们的地址分别存为ping1ping2
  3. 再调用skynet.send,让主服务向ping1发送名 为“start”的消息(图中的阶段),附带一个参数ping2
  4. 最后,主服务完成使命,退出

(2)ping服务

         在skynet/examples目录下新建ping.lua文件,输入如下所示代码:

local skynet = require "skynet"local CMD = {}function CMD.start(source, target)skynet.send(target, "lua", "ping", 1)
endfunction CMD.ping(source, count)local id = skynet.self()skynet.error("["..id.."] recv ping count="..count)skynet.sleep(100)skynet.send(source, "lua", "ping", count+1)
endskynet.start(function()skynet.dispatch("lua", function(session, source, cmd, ...)local f = assert(CMD[cmd])f(source,...)end)
end)
    为使代码简洁,两个回调方法都使用了匿名函数。代码说明:
  1. 先用skynet.start初始化服务;
  2. 然后在回调方法中调用skynet.dispatch,指定lua类型消息的处理方法,参数session代表消息的唯一id,可暂时先不管。source代表消息来源,指发送消息的服务地址,cmd代表消息名,“...”是一个可变参数,内容由发送方的skynet.sendskynet.call指定。       
  3. 收到其他服务的消息后,查找CMD[cmd]这个方法是否存 在,如果存在就调用它;
  4. ping1服务收到主服务的“start”消息时,程序会调用CMD.start(source, ...)。其中,参数source代表消息来源,其他参数由发送方传送。
  5. ping服务可以接收两种消息:一种是主服务发来的start消息;另一种是其他ping服务发来的ping消息。
        主服务会在启动两个ping服务后给ping1发送start消息,语句 是“skynet.send(ping1, "lua", "start", ping2),最后一个参数对应CMD.start的参数target,代表要让ping1发消息给谁。ping1收到后,会给ping2发送一条ping消息,附带参数“1”ping2收到后,执行CMD.ping,参数“1”对应参数countping2也会给ping1(发送方 source)发送ping,并把记数值count1,如此往复。

(3)配置文件

skynet/examples目录下新建PingConfig文件,然后把config中的内容复制过来稍加修改,内容如下所示:
include "config.path"thread = 8
logger = nil
logpath = "."
harbor = 0
start = "main_ping"	-- main script
bootstrap = "snlua bootstrap"	-- The service for bootstrap
-- snax_interface_g = "snax_g"
cpath = root.."cservice/?.so"
-- daemon = "./skynet.pid"

(4)运行结果

        最后打开终端,输入如下指令,显示运行结果。

        其中0000000a10代表ping2的地址(一个十六进制一个十进制,它们是相同的值,根据不
同配置,读者看到的数值可能不同),000000099代表ping1的地址。ping2先打印出计数值1
接着 ping1打印出计数值2,然后ping2再打印出计数值3,以此类推。