目 錄
9. 協定過濾器,解決一包多發、粘包、備援資料... 2
9.1 概述... 2
9.2 實際問題... 2
9.3 5種過濾器及二次開發... 5
9.4 裝置驅動開發注意事項... 6
9.5 宿主程式服務執行個體配置注意事項... 6
9. 協定過濾器,解決一包多發、粘包、備援資料
9.1 概述
通訊中涉及到資料包的概念,是通訊協定中的資料組成形式。針對這塊内容,說簡單也簡單,說複雜也複雜。需要我們系統性的把問題考慮全面,并用代碼實作。
在工業領域也有極端的情況出現,早些年做通訊的時候,資料標頭、包尾、資料長度、資料校驗位都對,但是就是解析出來的資料不正确,這種情況不會經常出現,但是在某種特殊應用環境可能會頻繁出現,後來經過分析得出結論:可能是由于地質電磁幹擾引起的。但是也有技術上的設計缺陷,例如:資料校驗位是累加和,改成CRC是不是就不會出來這個問題了;另外對于增量資料,應該有補發機制等等。
9.2 實際問題
參考協定:
《連載 | 物聯網架構ServerSuperIO教程》-4.如開發一套裝置驅動,同時支援序列槽和網絡通訊- 1. 一包多發及解決
多包發送資料是應用環境中的一種情況或一個問題,并不是我們會這樣實際應用,而是說在接收過程中多次接收資料才能完整接收用戶端一次發送的資料,可能由于網絡環境或發送資料端造成的,示意如下圖:

例如實時資料的完整包為:55 AA 00 61 43 7A 00 00 43 B4 15 0D。那麼接收資料的時候,第一次接收到:55 AA 00 61 43 7A 00 00 43 B4 15,第二次接到:0D。按通訊協定應該能夠把這兩次接收的資料進行自動拼接,形成完整的資料并進行解析。
ServerSuperIO設定了協定過濾器,可以解決這個問題,如下圖:
- 2. 粘包及解決
我原來并不知道粘包這個概念,後來在網上看文章才明白。在通訊領域中也是經常會遇到的問題。也就是多包資料一次性的接收,那麼就要合理的進行拆包。還有一種情況,就是多包半的資料一次性的接收,那半包的資料結合“1.一包多發及解決”來解決這個問題,示意如下圖:
ServerSuperIO設定了協定過濾器,可以解決這個問題,如下圖:
- 3. 備援資料的出現及解決
在工業領域受電纜或環境的電磁幹擾,以及接頭虛接等,這種情況極有可能出現。如果幹擾的備援資料夾雜在一個協定包中間,那麼校驗出合法的資料很困難。如果幹擾的備援資料夾雜在兩個協定包中間,那麼就可以通過協定過濾來實作識别出有用的資料。示意如下圖:
ServerSuperIO設定了協定過濾器,可以解決這個問題,如下圖:
9.3 5種過濾器及二次開發
FixedEndReceiveFliter:固定結尾的協定過濾器。
FixedHeadAndEndReceiveFliter:固定開頭和結尾的協定過濾器。
FixedHeadAndLengthReceiveFliter:固定開頭和長度的協定過濾器。
FixedHeadReceiveFliter:固定開頭的協定過濾器。
FixedLengthReceiveFliter:固定長度的協定過濾器。
這5個過濾器都繼承自IReceiveFilter接口,也可以繼承這個接口進行二次開發,定制自己的協定過濾器。代碼工程如下圖:
9.4 裝置驅動開發注意事項
對于開發裝置驅動,在初始化過程中可以增加這個驅動的協定過濾器,代碼如下:
public override void Initialize(string devid)
{
this.Protocol.InitDriver(this.GetType(),new FixedHeadAndEndReceiveFliter(new byte[] {0x55,0xaa},new byte[] {0x0d} ));
……
}
9.5 宿主程式服務執行個體配置注意事項
在配置參數中需要配置:StartReceiveDataFliter = true,協定過濾器才能起到作用。代碼如下:
static void Main(string[] args)
{
DeviceSelfDriver dev2 = new DeviceSelfDriver();
dev2.DeviceParameter.DeviceName = "網絡裝置";
dev2.DeviceParameter.DeviceAddr = 1;
dev2.DeviceParameter.DeviceID = "1";
dev2.DeviceDynamic.DeviceID = "1";
dev2.DeviceParameter.DeviceCode = "1";
dev2.DeviceParameter.NET.RemoteIP = "127.0.0.1";
dev2.DeviceParameter.NET.RemotePort = 9600;
dev2.CommunicateType = CommunicateType.NET;
dev2.Initialize("1");
IServer server = new ServerManager().CreateServer(new ServerConfig()
{
ServerName = "服務1",
ComReadTimeout = 1000,
ComWriteTimeout = 1000,
NetReceiveTimeout = 1000,
NetSendTimeout = 1000,
ControlMode = ControlMode.Self,
SocketMode = SocketMode.Tcp,
StartReceiveDataFliter = true,
ClearSocketSession = false,
StartCheckPackageLength = false,
CheckSameSocketSession = false,
DeliveryMode = DeliveryMode.DeviceIP,
});
server.AddDeviceCompleted += server_AddDeviceCompleted;
server.DeleteDeviceCompleted+=server_DeleteDeviceCompleted;
server.Start();
server.AddDevice(dev2);
while ("exit" == Console.ReadLine())
{
server.Stop();
}
}
1.
[連載]《C#通訊(序列槽和網絡)架構的設計與實作》2.[
開源]C#跨平台物聯網通訊架構ServerSuperIO(SSIO)介紹2.
應用SuperIO(SIO)和開源跨平台物聯網架構ServerSuperIO(SSIO)建構系統的整體方案3.
C#工業物聯網和內建系統解決方案的技術路線(資料源、資料采集、資料上傳與接收、ActiveMQ、Mongodb、WebApi、手機App)5.ServerSuperIO開源位址:
https://github.com/wxzz/ServerSuperIO物聯網&內建技術(.NET) QQ群:54256083