0%

[DotnetCore]Socket程式實作-解析封包

前情提要

筆者在上篇把該有的Socket底層元件相關的程式碼依照分類貼出,筆者分幾個筆記來詳細解釋相關設計概念,此篇以最上層Client端解析封包作業為例,解釋筆者的設計概念。

內容

筆者用過幾個Event設計的原件,基本上可以從dotnet預設的套件就可以看出諸多此類的設計,筆者自己也加工過幾個,例:SMTP Send Mail,使用ProcessInfo執行bat file皆使用上此類技巧。

以筆者使用的NetCoreServer來說,他所設計的方式是繼承他原有的物件,將幾個socket發生的事件處裡邏輯封裝成virtual的形式,你可以override成自己想要的樣子,以套件github頁面上提供的範例來說,由幾個處裡事件方法是可以複寫的,如下:

  • Server/Session/Client
    • OnConnected
    • OnDisconnected
    • OnReceived
    • OnError

筆者將擴大成將常用的事件定義成契約interface,才會出現IServerIClient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public interface IServer
{
/// <summary>
/// 傳送封包
/// </summary>
/// <param name="data"></param>
void Send(byte[] data);
/// <summary>
/// 回傳特定Client封包
/// </summary>
/// <param name="clientId"></param>
/// <param name="data"></param>
void Send(Guid clientId, byte[] data);
/// <summary>
/// Client連線事件
/// </summary>
/// <param name="clientId"></param>
void Server_OnAccept(Guid clientId);
/// <summary>
/// 傳送事件
/// </summary>
/// <param name="sent"></param>
/// <param name="pending"></param>
void Server_OnSend(long sent, long pending);
/// <summary>
/// 特定Client封包接受事件
/// </summary>
/// <param name="clientId"></param>
/// <param name="buffer"></param>
void Server_OnReceive(Guid clientId, byte[] buffer);
/// <summary>
/// 特定Client關閉
/// </summary>
/// <param name="clietId"></param>
void Server_OnClose(Guid clietId);
}
1
2
3
4
5
6
7
8
public interface IClient
{
void Client_OnClose();
void Client_OnReceive(byte[] data);
void Client_OnConnect(bool obj);
void Client_OnSend(long sent, long pending);
void Send(byte[] data, int offset, int length);
}

筆者在中間有換過一次底層套件,NetCoreServer還是第二次套用的底層元件,為這個套件調整過一次上述Interface,不過因為上層相依的部份只有OnReceive,筆者當初的想法是對於最上層Client使用端來說只有解析封包這件事是客製化的,其他行為是不會改變的,因此才有了IAnalyzeService

1
2
3
4
5
public interface IAnalyzeService
{
void ClientAnalyze(byte[] receiveBytes);
void ServerAnalyze(Guid arg1, byte[] arg2);
}

可以看出筆者只定義了Server收到封包後的解析邏輯以及Client收到封包後的解析邏輯,筆者於各自的BaseServer及BaseClient的OnReceive中呼叫IAnalyzeService中對應的Method﹔

1
2
3
4
5
6
7
//BaseServer
public void Server_OnReceive(Guid clientId, byte[] data)
{
//...以上省略
_analyzeService.ServerAnalyze(clientId, data);
//...以下省略
}
1
2
3
4
5
6
7
//BaseClient
public void Client_OnReceive(byte[] data)
{
//...以上省略
_analyzeService.ClientAnalyze(data);
//...以下省略
}

意即最上層Client使用端只要注入對應的實作IAnalyzeService,只要OnReceive事件觸發,底層元件會呼叫其對應的解析封包方法。

結論

藉由這邊來解釋一下底層元件與最上層Client使用端是如何連結的。