sproto

来源:互联网 发布:弹丸论破v3 知乎 编辑:程序博客网 时间:2024/06/06 05:22

sproto是一套由skynet自身提供的协议,类似google protobuffers,但设计更简单,也更利于lua使用,同时还提供了一套简单的rpc方案.


RPC

需要一个消息包的主体格式,它必须有一个叫type的字段,描述RPC到底是哪一条消息,还要有一个session字段来表示回应消息的对应关系,通常这两个字段都被定义成integer.

.package {    type 0 : integer    session 1 : integer}
使用sproto的rpc框架,每条消息都会以这条消息开头,接上真正的消息内容;连接在一起后用sproto的0-pack方式打包,这个数据包并不包含长度信息,所以真正在网络上传输,还需要添加长度信息,方便分包,如果使用skynet的gate模块的话,约定了以两字节大端表示的长度加内容的方式分包.


构造一个sproto rpc 的消息处理器,应使用:

local host = sproto:host(packagename)  -- packagename 默认值为 "package" 即对应前面的 .package 类型。你也可以起别的名字。
这条调用会返回一个host对象,用于处理接受的消息.
host:dispatch(msgcontent)
上面这条代码用于处理一条信息.这里的msgcontent 也是一个字符串,或是一个userdata(指针)加一个长度.它应符合上述的以sproto的0-pack方式打包的包格式.
dispatch 调用有两种可能的返回类别,由第一个返回值决定:
REQUEST:第一个返回值为"REQUEST"时,表示这是一个远程请求,如果请求包中没有session字段,表示该请求不需要回应,这时,第2和第3个返回值分别为消息类型名(即在sproto定义中提到的某个以.开头的类型名),以及消息内容(通常是一个table);如果请求包中有session字段,那么还会有第4个返回值:一个用于生产回应包的函数.
RESPONSE:第一个返回值为"RESPONSE"时,第2和第3个返回值分别为session和消息内容,消息内容通常是一个table,但也可能不存在内容(仅仅是一个回应确认).
local sender = host:attach(sp)  -- 这里的 sp 指向外发出的消息协议定义。
attach可以构造一个发送函数,用来将对外请求打包编码成可以被dispatch正确解码的数据包.
这个sender函数接受三个参数(name,args,session).name是消息的字符串名,args是一张保存用消息内容的table,而session是你提供的唯一识别号,用于让对方正确的回应,当比的协议不规定要回应时,session可以不给出,同样,args也可以为空.
Sproto Loader

由于 skynet 采用的是多 lua 虚拟机。如果在每个 VM 里都加载相同的 sproto 协议定义就略显浪费。所以 skynet 还提供了一个叫 sprotoloader 的模块来共享它们。

其实现原理是在 C 模块中提供了 16 个全局的 slot ,可以通过 sprotoloader.register 或 sprotoloader.save 在初始化时,加载需要的协议,并保存在这些 slot 里。通常我们只需要两个 slot ,一个用于保存客户端到服务器的协议组,另一个用于保存服务器到客户端的协议组。分别位于 slot 1 和 2 。

这样,在每个 vm 内,都可以通过 sprotoloader.load 把协议加载到 vm 中。

注意:这套 api 并非线程安全。所以必须自行保证在初始化完毕后再做 load 操作。(load 本身是线程安全的)。


具体的使用范例,可以参考 examples 下的 agent.lua 以及 examples 下的 client.lua 。理解 RPC 是如何工作的

0 0
原创粉丝点击