zoukankan      html  css  js  c++  java
  • 基于动态代理的WebAPI/RPC/webSocket框架,一套接口定义,多个通讯方式

    API/RPC/webSocket三个看起来好像没啥相同的地方,在开发时,服务端,客户端实现代码也大不一样

    最近整理了一下,通过动态代理的形式,整合了这些开发,都通过统一的接口约束,服务端实现和客户端调用

    基于这样的形式,WebAPI/RPC/webSocket只需要定义一套接口,就能达到通用的效果

     示例接口约束

        public class TestObj
        {
            public string Name { get; set; }
        }
        public interface ITestService
        {
            void Login();
            bool Test1(int a,int? b,out string error);
            TestObj Test2(TestObj obj);
        }
        public class TestService : AbsService, ITestService
        {
            [LoginPoint]
            public void Login()
            {
                SaveSession("hubro", "7777777777", "test");
            }
    
            public bool Test1(int a, int? b, out string error)
            {
                var user = CurrentUserName;
                var tag = CurrentUserTag;
    
                error = "out error";
                Console.WriteLine(a);
                Console.WriteLine(b);
                return true;
            }
    
            public TestObj Test2(TestObj obj)
            {
                Console.WriteLine(obj.ToJson());
                return obj;
            }
        }

    上面是一个标准接口和接口实现,并继承了AbsService,

    Login方法标注了LoginPoint特性,表示登录切入点,调用此接口时首先得调用此方法,方法内SaveSession存储登录状态

    Test1方法内使用了CurrentUserName,以获取登录方法保存的Session

    特点:

    • 通过接口约束服务端和客户端调用,参数定义透明化,out也支持
    • 真正的方法远程调用,任意参数类型,个数
    • 集成登录认证逻辑,自定义登录认证过程,也可以自定义Session实现
    • 集成简单数据签名,不用费心数据安全问题

    技术实现:

    • Dynamitey实现接口类型代理
    • DotNetty实现TCP通讯
    • 对象二进制序列化

    RPC调用

    服务端

    var server = new ServerCreater().CreatetRPC(805);
                server.CheckSign();
                server.SetSessionManage(new SessionManage());
                server.Register<ITestService, TestService>();
                server.Start();

    CreateRPC是一个扩展方法,引用CRL.RPC获取

    SetSessionManage,自定义Session存储,默认是内存里

    CheckSign 处理请求时,进行参数签名验证

    客户端接口调用

    var clientConnect = new RPCClientConnect("127.0.0.1", 805);
                clientConnect.UseSign();
                var service = clientConnect.GetClient<ITestService>();
            label1:
                service.Login();
                Console.WriteLine("loginOk");
                int? a = 1;
                string error;
                service.Test1(1, a, out error);
                Console.WriteLine("error:" + error);
                var obj2 = service.Test2(new TestObj() { Name = "test" });
                Console.WriteLine("obj2:" + obj2.ToJson());
                Console.ReadLine();
                goto label1;
    

      

    客户端先调用login方法进行登录,并记录服务端返回的token

    Test1方法将token回传给服务器以验证登录状态,并进行远程调用

    当调用了UseSign方法,就会对提交的参数进行签名,签名KEY为登录后服务端返回的TOKEN,服务端同样按此对签名进行比较 

    动态webApi

    同样基于上文结构,接口定义就不粘贴了

    服务端定义

    var server = new ServerCreater().CreatetApi();
                server.CheckSign();
                server.SetSessionManage(new SessionManage());
                server.Register<ITestService, TestService>();
                var listener = new ServerListener();
                //listener.Start("http://localhost:809/");//自定义监听
    

     

    如果宿主是.NET网站 在web.config增加处理module

    <system.webServer>
        <modules>
          <add name="DynamicModule" type="CRL.DynamicWebApi.DynamicModule" />
        </modules>
      </system.webServer>
    

      

    如果是单独程序,启动ServerListener即可

    客户端调用

    var clientConnect = new CRL.DynamicWebApi.ApiClientConnect("http://localhost:53065");
                //var clientConnect = new CRL.DynamicWebApi.ApiClientConnect("http://localhost:8022");
                clientConnect.UseSign();
                var service = clientConnect.GetClient<ITestService>();
            
            label1:
                service.Login();
                Console.WriteLine("loginOk");
                int? a = 1;
                string error;
                service.Test1(1, a, out error);
                Console.WriteLine("error:" + error);
                var obj2 = service.Test2(new TestObj() { Name = "test" });
                Console.WriteLine("obj2:" + obj2.ToJson());
                Console.ReadLine();
                goto label1;

    WebSocket

    WebSocket是一个比较特殊的方式,常用来做双工通讯的方式,客户端能往服务端发送数,服务端也能往客户端发送据

    除去服务端往客户端发数据,也可以采用接口调用的形式实现,在这里,服务端往客户端发送数据,客户端采用了订阅的方式

    服务端实现

    var server = new ServerCreater().CreatetWebSocket(8015);
                server.CheckSign();
                server.SetSessionManage(new SessionManage());
                server.Register<ITestService, TestService>();
                server.Start();
                new CRL.Core.ThreadWork().Start("send", () =>
                {
                    var socket = server.GetServer() as CRL.WebSocket.WebSocketServer;
                    socket.SendMessage("hubro", new socketMsg() { name = DateTime.Now.ToString() }, out string error);
                    Console.WriteLine("send msg");
                    return true;
                }, 10);
    

      

    上面演示代码,服务端开启了一个线程,定时往客户端"hubro"发送数据 socket.SendMessage

    客户端实现

    var clientConnect = new CRL.WebSocket.WebSocketClientConnect("127.0.0.1", 8015);
                clientConnect.UseSign();
                clientConnect.SubscribeMessage<socketMsg>((obj) =>
                {
                    Console.WriteLine("OnMessage:" + obj.ToJson());
                });
                clientConnect.StartPing();
                var service = clientConnect.GetClient<ITestService>();
            label1:
    
                service.Login();
                Console.WriteLine("loginOk");
                int? a = 1;
                string error;
                service.Test1(1, a, out error);
                Console.WriteLine("error:" + error);
                var obj2 = service.Test2(new TestObj() { Name = "test" });
                Console.WriteLine("obj2:" + obj2.ToJson());
                Console.ReadLine();
                goto label1;

    clientConnect.SubscribeMessage就是订阅消息了,通过订阅的方式,处理服务端发送的数据

    可以看到以上各种形式,服务端实现和客户端调用基本相同,定义的接口能重复使用,做接口通讯效果杠杠的

    具体实现方式和细节功能参见源码和demo,已经开源,请自行下载

    源码地址:

    CRL:

    https://github.com/hubro-xx/CRL5

    RCP:

    https://github.com/hubro-xx/CRL5/tree/master/RPC

    WebAPI:

    https://github.com/hubro-xx/CRL5/tree/master/DynamicWebApi

    WebSocket:

    https://github.com/hubro-xx/CRL5/tree/master/WebSocket

  • 相关阅读:
    正则表达式
    HDU 2066 多源最短路
    UVA 11039 模拟
    Concrete Mathematics Chapter 1 Warmups
    List differences between JAVA and C++
    uva 11107Life Forms
    poj 1509 Glass Beads
    poj 3581
    网络流建图
    图论算法----网络流
  • 原文地址:https://www.cnblogs.com/hubro/p/11652687.html
Copyright © 2011-2022 走看看