C#实现RPC(远程过程调用)


仿照这位Up主写的:Up主视频
项目地址:在这


首先 什么事RPC

  • 看知乎上这几个回答
  • 就像在本地调用函数一样去调用远程的函数,但是本地和远端拥有不同内存空间直接调用肯定是没有办法的,所以思路就是,我在本地调用方法,内部实现利用网络消息传输,去调用远程的函数。本质还是消息协议,只不过是在解析完协议又封装了一层用于调用具体的方法

注意

  • up主用的的是大端(高尾端),我这个因为习惯用的是小端(低尾端)
  • 剩下的就是写法问题,没什么太大差别
  • 只是为了了解具体的思路,里面存在很多问题,比如没有处理粘包分包问题,字节缓存,运行时直接利用反射等等。

客户端(调用端)

  • 首先我们上面说的就像在本地调用函数一样去调用远程的函数。仔细想想,A调用函数Func实际执行的是B的Func。好了,现在有了一个规范了两端都要实现同样的函数。看红字强调了实现这2个字,所以我们采用接口形式,两端都实现接口IUserInfo需要实现是登陆与加法
    interface IUserInfo
    {
   
   
        bool Login(string account, string pwd);

        int Add(int a, int b);
    }
  • 在看具体实现先看一下使用的几个数据结构,内置对象的枚举,ArgTypeInfo是参数附带类型枚举。
    public class ArgTypeInfo
    {
   
   
        public TypeEnum argType {
   
    get; set; }

        public object value {
   
    get; set; }
    }

    public enum TypeEnum
    {
   
   
        Void = 0,
        Int,
        Bool,
        String
    }
  • EncodeSendPackage主要用于将接口名称、方法名称、参数个数、返回类型以及参数,然后依照下面的RPC协议格式进行编码得到字节数组。
/* 
	RPC协议格式
	接口名长度(1字节)、接口名, 方法名长度(1字节),方法名,参数长度(1字节),返回类型,
	参数序列(string类型前面有字符串长度),int类型是32位
*/ 

private static byte[] EncodeSendPackage(string interfaceName, string methodName, int argLen, TypeEnum returnType, List<ArgTypeInfo> argTypeInfos
            )
        {
   
   
            // 接口名称
            List<byte> byteList = new List<byte>();
            byte[] interfaceBytes = Encoding.UTF8.GetBytes(interfaceName);
            byteList.Add((byte)interfaceBytes.Length);
            byteList.AddRange(interfaceBytes);
            // 方法名称
            byte[] methodNameBytes = Encoding.UTF8.GetBytes(methodName);
            byteList.Add((byte)methodNameBytes.Length);
            byteList.AddRange(methodNameBytes);

            // 参数个数
            byteList.Add((byte)argLen);

            // 返回类型
            byteList.Add((byte)returnType);

            // 参数列表
            foreach (ArgTypeInfo ati in argTypeInfos)
            {
   
   
                byteList.Add((byte)ati.argType);
                if (ati.argType == TypeEnum.String)
                {
   
   
                    string value = ati.value as string;
                    byte[] stringBytes = Encoding.UTF8.GetBytes(value);
                    byteList.Add((byte)stringBytes.Length);
                    byteList.AddRange(stringBytes);
                }
                else if (ati.argType == TypeEnum.Int)
                {
   
   
                    int value = Convert.ToInt32(ati.value);
                    byte[] intBytes = Int2Bytes(value);
                    byteList.AddRange(intBytes);
                }
                else if (ati.argType == TypeEnum.Bool)
                {
   
   
                    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值