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