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
