博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
leaf源码分析(一)----chanrpc
阅读量:4031 次
发布时间:2019-05-24

本文共 3290 字,大约阅读时间需要 10 分钟。

本文公众号链接为:

 

 

 

Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。

 

阅读中文文档,其中介绍的是

 

leaf/chanrpc 提供了一套基于 channel 的 RPC 机制,用于游戏服务器模块间通讯。chanrpc提供了三种模式

  1. 同步模式,调用并等待 ChanRPC 返回

  2. 异步模式,调用并提供回调函数,回调函数会在 ChanRPC 返回后被调用

  3. Go 模式,调用并立即返回,忽略任何返回值和错误

 

那么下面看源码

源码目录为:

 

 

先看看github.com/name5566/leaf/chanrpc/example_test.go,里面演示了chanrpc的具体用法

chanrpc分为server和client两个部分

 

以上代码中是server的一个过程

1、初始化了一个server。

2、接着,注册了server提供的rpc函数。rpc支持三种类型

func([]interface{})                           参数为[]interface,无返回值func([]interface{}) interface{}           参数为[]interface,返回值为interfacefunc([]interface{}) []interface{}         参数为[]interface,返回值为[]interface

3、最后server开启Exec执行rpc函数

 

以上为client过程

1、创建了client

2、同步调用。提供了集中调用方法。可以根据返回值分类来记忆:

Call0,Call1,CallN

 

3、异步调用。异步与同步的区别在于,异步执行调用完就会直接返回,但其注册了cb(call back)回调函数。在最后会等待异步执行完毕后,执行cb

4、Go模式。和异步调用的区别就是无cb。也是立即返回的。

 

用法分析完后,看具体的源码

 

github.com/name5566/leaf/chanrpc/chanrpc.go

基本数据结构RetInfo

 

 

ret interface{}      记录返回值,有三种类型err error              记录errcb interface{}      保存上下文中的Call back函数

 

基本数据结构CallInfo

 

f       interface{}                rpc调用的函数args    []interface{}           参数chanRet chan *RetInfo       传递ret的chancb      interface{}              保存上下文中的Call back函数

 

Server

 

Server数据结构

functions map[interface{}]interface{}           用于保存注册rpc函数ChanCall  chan *CallInfo                            用于接收rpc调用chan

以上是Server初始化。注意其中l,是chancall的容量,意味着,异步调用时候能够异步传递多少函数。

Register

 

以上是注册接口(注意:此处并非线程安全的)

1、通过switch来对类型做一个判断。default中,则是不支持的类型,将会panic

2、判断是否重复注册

3、注册,其实就是放到map中。

 

Exec

回顾下用法

在github.com/name5566/leaf/chanrpc/example_test.go中

 

 

 

从以上代码中可以看出,就是从ChanCall中,取出CallInfo信息,然后执行。

继续跟踪

 

根据不同的rpc函数类型,封装不同的RetInfo。继续跟踪

 

1、当client调用的时候,没有注册chanret时,也就是为nil,不需要传递返回值,则直接返回不处理。否则继续往下处理

2、将client调用rpc时候,注册的cb,传递到RetInfo中。并将RetInfo发送到CallInfo中的chanRet中,将ret信息和cb传递给client。

 

到此Server所处理的流程都已经完了

 

Client

 

 

s               *Server                            对应的ServerchanSyncRet     chan *RetInfo             同步调用时候,用于接收ret的chanChanAsynRet     chan *RetInfo            异步调用的时候,用于接收ret和cb的chanpendingAsynCall int                           异步调用的计数器

 

初始化

两种模式

 

1、先初始化client结构体。这里要注意的是

同步chanSyncRet容量为1

异步cahnAsynRet的容量是初始化为参数l的。

2、将其Attach,附属到server中。其实就是将s初始化到client中的成员变量s

这种模式需要调用两次函数

 

这种模式,是将初始化和Attach封装到了一起。

 

同步调用

 

步骤是一样的

1、查找函数f

2、远程调用call。其中chanRet赋值的是chanSyncRet,block设置为true。这个是区别于异步调用模式的。

3、从chanSyncRet中接收ret,并将ret返回给上一层

 

f函数,功能就是一个,从server的注册函数中,查找到对应id的函数,将其返回。

其中做了一些函数的检查。

 

call函数:将CallInfo信息通过server的chancall发送给server。

1、同步模式,会阻塞等待

2、异步模式,会直接发送。如果chancall的容量不够,则会直接执行default。

在NewServer的时候,有个参数l,就是用来设置chancall的容量的。

 

异步调用

 

上述步骤

1、参数分割,最后一个参数是cb

2、对cb函数,类型检查,不支持的函数的话,则panic

3、判断异步调用是不是超出了异步chanAsynRet的容量,如果是,则直接将err返回

4、调用asynCall,并计数pendingAsynCall

 

以上步骤

1、从f中查找对应id的rpc函数。如果未查到,则直接通过chanAsynRet将err返回

2、call,这里面chanRet赋值的是chanAsynRet。blcok设置为false。这是区别于同步调用的。

 

异步执行结果

 

 

通过RetInfo中获取到cb函数,通过不同类型,进行cb调用。三种类型如下

ri.cb.(func(error))(ri.err)   ri.cb.(func(interface{}, error))(ri.ret, ri.err)   ri.cb.(func([]interface{}, error))(assert(ri.ret), ri.err)

 

Go模式

 

其实这个模式是最简单的

1、查找对应id的rpc函数

2、构建CallInfo发送到chancall中

不需要构建返回,也没有cb

 

close

还有一个没讲解的那就是close

 

server close

1、会先将chancall关闭掉

2、处理chancall中剩余的rpc调用。并不会执行,而是执行返回错误

 

client close

同步的是不用处理的,肯定会处理结束

主要的是异步的,异步有个计数器,会一直处理等待计数器为0

 

 

 

龚浩华

月牙寂道长

QQ 29185807

2018年04月17日

如果你觉得本文对你有帮助,可以转发分享到你的朋友圈,让更多人一起学习。

第一时间获取文章,可以关注本人公众号:月牙寂道长,也可以扫码关注

 

你可能感兴趣的文章
Android 跨应用程序访问窗口知识点总结
查看>>
各种排序算法的分析及java实现
查看>>
SSH框架总结(框架分析+环境搭建+实例源码下载)
查看>>
js弹窗插件
查看>>
自定义 select 下拉框 多选插件
查看>>
js判断数组内是否有重复值
查看>>
js获取url链接携带的参数值
查看>>
gdb 调试core dump
查看>>
gdb debug tips
查看>>
arm linux 生成火焰图
查看>>
jtag dump内存数据
查看>>
linux和windows内存布局验证
查看>>
linux config
查看>>
linux insmod error -1 required key invalid
查看>>
linux kconfig配置
查看>>
linux不同模块completion通信
查看>>
linux printf获得时间戳
查看>>
C语言位扩展
查看>>
linux dump_backtrace
查看>>
linux irqdebug
查看>>