RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。

首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

以上摘自,百度百科。

第一个问题是Why?通过一个特定协议定义,我们可以脱离常规的协议定义。使用一个通用协议来达到远程调用的过程。
   第二个问题协议?我们选择的是Json协议,好处就是灵活多变,可以使用一个字符串表示所有对象。
      坏处就是解析略慢,因为没有长度标识,所以不能搜索,只能一次性解析。不过在于交换场景,这个一点问题都没。

这里是协议定义:

请求定义:

    public partial class RequestObj
{
/// <summary>
/// 命令(一般为方法名称)
/// </summary>
public string cmd { get; set; } /// <summary>
/// 名字空间
/// </summary>
public string ns { get; set; } /// <summary>
/// 参数
/// </summary>
public object[] args { get; set; } /// <summary>
/// 请求序号
/// </summary>
public int cid { get; set; } /// <summary>
/// 如果WebSocket才使用
/// </summary>
public string tk { get; set; } /// <summary>
/// 主动版本同步,0则忽略
/// </summary>
public int ver { get; set; } }

响应定位:

  /// <summary>
/// 返回数据
/// </summary>
public partial class ResponseObj
{
/// <summary>
/// 返回数据对象
/// </summary>
public object result { get; set; } /// <summary>
/// 是否出错信息
/// 默认0 无出错信息
/// </summary>
public int error { get; set; } /// <summary>
/// 请求序号
/// </summary>
public int cid { get; set; } /// <summary>
/// 差异数据
/// </summary>
public OpChangeItem[] opstr{ get; set; } }

疑问:
object,这是一个不科学的设定?这边待保留。
OpChangeItem,这个是什么鬼?依然保留。

这里我们尝试来进行一次调用构造。

特定方法:

	public class LocalTest
{
/// <summary>
/// 添加一个消息
/// </summary>
public static void AddMessage(string topic, string messageBody)
{
//这里什么都不干
}
}

发送消息:

{"args":["Test","Message"],"cid":"1","cmd":"AddMessage","ns":"LocalTest","tk":null}

从以上我们可以解析出来

类名:LocalTest, 调用方法名:AddMessage,参数[topic : Test , messageBody:Message]

通过反射调用,我们就完成了执行的目的。

然后是返回值:

调用完成后,返回消息:

{"result": null , "error" : 0 ,"cid" : 1, "opstr":[] }

注:cid的设定是为了区分调用的请求源,如果你有多个调用同时发起,那么cid拿来区分你的来源,从而达到返回值的匹配。

从以上例子看出,我们调用了一个AddMessage方法,服务端进行了响应,然后什么事情都没发生。

我们这里的协议,抛开Opstr字段已经可以完整的描述一整个调用,因为返回值,和参数都用的object,
所以只要知道类型,那么可以通过json转换成对应的参数和类型,所以我们无需特别约定协议即可以得到特定的类型。

然后我们进行修改

		public void AddMessage(string topic, string messageBody,Action callback)
{
try
{
//这边进行一次封装,直接把当前的方法调用包装成请求,然后通过标记,判是否是本地执行,
//如果是本地执行,则执行本地
var __cid = WindNet.RemoteCall.Instance.DoCall(callback, this, "LocalTest.AddMessage", topic,messageBody);
if (WindNet.RemoteCall.Instance.IsLocal || __cid.isLocal)
{
//原本执行的事情
//这里什么都不干
if(callback!=null)
callback();
}
//如果是远程调用,则什么都不干。
}
catch (Exception)
{
WindNet.RemoteCall.Instance.DoError(e);
throw;
}
}

  

首先我们加了个callback参数,当执行完毕之后,我们调用一下callback
因为网络是一个不稳定的玩意,如果你一直在等待,则可能卡住主线程,在游戏中你的渲染就无法进行,那么我们使用callback来进行流程处理。
以及返回值的处理。
流程就是这样,你调用函数-》构造请求-》发起请求-》 服务器返回后-》调用callbak
如果我们把IsLocal 设为true
流程就是
你调用函数-》构造请求(不发出)-》执行本地方法-》执行callback

经过我们的设计,我们在执行函数前进行了一次简单的拦截,然后通过通用协议和cid进行callback的匹配,然后达到正确的回调过程。

游戏编程系列[1]--游戏编程中RPC协议的使用的更多相关文章

  1. WCF编程系列(六)以编程方式配置终结点

    WCF编程系列(六)以编程方式配置终结点   示例一中我们的宿主程序非常简单:只是简单的实例化了一个ServiceHost对象,然后调用open方法来启动服务.而关于终结点的配置我们都是通过配置文件来 ...

  2. Java并发编程系列-(1) 并发编程基础

    1.并发编程基础 1.1 基本概念 CPU核心与线程数关系 Java中通过多线程的手段来实现并发,对于单处理器机器上来讲,宏观上的多线程并行执行是通过CPU的调度来实现的,微观上CPU在某个时刻只会运 ...

  3. java并发编程系列原理篇--JDK中的通信工具类Semaphore

    前言 java多线程之间进行通信时,JDK主要提供了以下几种通信工具类.主要有Semaphore.CountDownLatch.CyclicBarrier.exchanger.Phaser这几个通讯类 ...

  4. 学习ASP.NET Core Blazor编程系列十——路由(中)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  5. 游戏编程系列[2]--游戏编程中RPC与OpLog协议的结合--序

    在系列[1]中,我们展示了RPC调用协议的定义以及演示,通过方法定义以及协议约定,进行了协议约定以及调用过程的约定.然而,实际上在游戏中,调用过程之后,需要传输相对多的数据给服务端. 常用场景,客户端 ...

  6. 游戏编程系列[1]--游戏编程中RPC协议的使用[3]--体验

    运行环境,客户端一般编译为.Net 3.5 Unity兼容,服务端因为用了一些库,所以一般为4.0 或往上.同一份代码,建立拥有2个项目.客户端引用: WindNet.Client服务端引用: OpL ...

  7. 游戏编程系列[1]--游戏编程中RPC协议的使用[2]--Aop PostSharp篇

    上一篇我们使用了一个通用JSON协议约定来进行达到远程调用的目的.但是从实现上,我们需要不断的在所有的方法上添加拦截,并且判断拦截,然后执行,这就达到了一个比较繁琐的目的. 之前我们尝试过使用代码生成 ...

  8. python编程系列---Pycharm快捷键(更新中....)

    以下是我常用到的Pycharm快捷键(还有很多,只是我暂时用的最多的就这些): 在开发过程中,经常使用一些快捷键会大大提高开发效率,不要因为看这多而不用,常用的就那些,用得多就都记住了,脱离鼠标,逼格 ...

  9. Hadoop中RPC协议小例子报错java.lang.reflect.UndeclaredThrowableException解决方法

    最近在学习传智播客吴超老师的Hadoop视频,里面他在讲解RPC通信原理的过程中给了一个RPC的小例子,但是自己编写的过程中遇到一个小错误,整理如下: log4j:WARN No appenders ...

随机推荐

  1. WebApi - 路由

    这段时间的博客打算和大家一起分享下webapi的使用和心得,主要原因是群里面有朋友说希望能有这方面的文章分享,随便自己也再回顾下:后面将会和大家分不同篇章来分享交流心得,希望各位多多扫码支持和点赞,谢 ...

  2. 谈谈一些有趣的CSS题目(七)-- 消失的边界线问题

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  3. [.NET] 利用 async & await 进行异步 IO 操作

    利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html  序 上次,博主 ...

  4. Android 7.1 - App Shortcuts

    Android 7.1 - App Shortcuts 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Shortcuts 文中如有纰漏,欢迎大家留言 ...

  5. 开源免费且稳定实用的.NET PDF打印组件itextSharp(.NET组件介绍之八)

    在这个.NET组件的介绍系列中,受到了很多园友的支持,一些园友(如:数据之巅. [秦时明月]等等这些大神 )也给我提出了对应的建议,我正在努力去改正,有不足之处还望大家多多包涵.在传播一些简单的知识的 ...

  6. [原创]关于Hibernate中的级联操作以及懒加载

    Hibernate: 级联操作 一.简单的介绍 cascade和inverse (Employee – Department) Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似 ...

  7. golang sync.WaitGroup bug

    注意,这个结构体,要是想在函数之间传来传去的话,必须要使用指针....... 这个结构体里没有 指针,这个类型可以说没有“引用特性”. 被坑了一晚上.特此记录.

  8. ComponentPattern (组合模式)

    import java.util.LinkedList; /** * 组合模式 * * @author TMAC-J 主要用于树状结构,用于部分和整体区别无区别的场景 想象一下,假设有一批连锁的理发店 ...

  9. 烂泥:redis3.2.3安装与配置

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 前一段时间写过一篇codis集群的文章,写那篇文章主要是因为当时的项目不支持redis自 ...

  10. Netty5使用自签证书实现SSL安全连接

    这次使用的Netty是最新的5.0 Alpha2版本,下载地址是:http://dl.bintray.com/netty/downloads/netty-5.0.0.Alpha2.tar.bz2,发布 ...