基於動態代理的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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM