目 錄
9. 協(xié)議過濾器,解決一包多發(fā)、粘包、冗余數(shù)據(jù)... 2
9.1 概述... 2
9.2 實(shí)際問題... 2
9.3 5種過濾器及二次開發(fā)... 5
9.4 設(shè)備驅(qū)動(dòng)開發(fā)注意事項(xiàng)... 6
9.5 宿主程序服務(wù)實(shí)例配置注意事項(xiàng)... 6
9. 協(xié)議過濾器,解決一包多發(fā)、粘包、冗余數(shù)據(jù)
9.1 概述
通訊中涉及到數(shù)據(jù)包的概念,是通訊協(xié)議中的數(shù)據(jù)組成形式。針對這塊內(nèi)容,說簡單也簡單,說復(fù)雜也復(fù)雜。需要我們系統(tǒng)性的把問題考慮全面,并用代碼實(shí)現(xiàn)。
在工業(yè)領(lǐng)域也有極端的情況出現(xiàn),早些年做通訊的時(shí)候,數(shù)據(jù)包頭、包尾、數(shù)據(jù)長度、數(shù)據(jù)校驗(yàn)位都對,但是就是解析出來的數(shù)據(jù)不正確,這種情況不會經(jīng)常出現(xiàn),但是在某種特殊應(yīng)用環(huán)境可能會頻繁出現(xiàn),后來經(jīng)過分析得出結(jié)論:可能是由于地質(zhì)電磁干擾引起的。但是也有技術(shù)上的設(shè)計(jì)缺陷,例如:數(shù)據(jù)校驗(yàn)位是累加和,改成CRC是不是就不會出來這個(gè)問題了;另外對于增量數(shù)據(jù),應(yīng)該有補(bǔ)發(fā)機(jī)制等等。
9.2 實(shí)際問題
參考協(xié)議:《連載 | 物聯(lián)網(wǎng)框架ServerSuperIO教程》-4.如開發(fā)一套設(shè)備驅(qū)動(dòng),同時(shí)支持串口和網(wǎng)絡(luò)通訊
- 1. 一包多發(fā)及解決
多包發(fā)送數(shù)據(jù)是應(yīng)用環(huán)境中的一種情況或一個(gè)問題,并不是我們會這樣實(shí)際應(yīng)用,而是說在接收過程中多次接收數(shù)據(jù)才能完整接收客戶端一次發(fā)送的數(shù)據(jù),可能由于網(wǎng)絡(luò)環(huán)境或發(fā)送數(shù)據(jù)端造成的,示意如下圖:
例如實(shí)時(shí)數(shù)據(jù)的完整包為:55 AA 00 61 43 7A 00 00 43 B4 15 0D。那么接收數(shù)據(jù)的時(shí)候,第一次接收到:55 AA 00 61 43 7A 00 00 43 B4 15,第二次接到:0D。按通訊協(xié)議應(yīng)該能夠把這兩次接收的數(shù)據(jù)進(jìn)行自動(dòng)拼接,形成完整的數(shù)據(jù)并進(jìn)行解析。
ServerSuperIO設(shè)置了協(xié)議過濾器,可以解決這個(gè)問題,如下圖:
- 2. 粘包及解決
我原來并不知道粘包這個(gè)概念,后來在網(wǎng)上看文章才明白。在通訊領(lǐng)域中也是經(jīng)常會遇到的問題。也就是多包數(shù)據(jù)一次性的接收,那么就要合理的進(jìn)行拆包。還有一種情況,就是多包半的數(shù)據(jù)一次性的接收,那半包的數(shù)據(jù)結(jié)合“1.一包多發(fā)及解決”來解決這個(gè)問題,示意如下圖:
ServerSuperIO設(shè)置了協(xié)議過濾器,可以解決這個(gè)問題,如下圖:
- 3. 冗余數(shù)據(jù)的出現(xiàn)及解決
在工業(yè)領(lǐng)域受電纜或環(huán)境的電磁干擾,以及接頭虛接等,這種情況極有可能出現(xiàn)。如果干擾的冗余數(shù)據(jù)夾雜在一個(gè)協(xié)議包中間,那么校驗(yàn)出合法的數(shù)據(jù)很困難。如果干擾的冗余數(shù)據(jù)夾雜在兩個(gè)協(xié)議包中間,那么就可以通過協(xié)議過濾來實(shí)現(xiàn)識別出有用的數(shù)據(jù)。示意如下圖:
ServerSuperIO設(shè)置了協(xié)議過濾器,可以解決這個(gè)問題,如下圖:
9.3 5種過濾器及二次開發(fā)
1
2
3
4
5
|
FixedEndReceiveFliter:固定結(jié)尾的協(xié)議過濾器。
FixedHeadAndEndReceiveFliter:固定開頭和結(jié)尾的協(xié)議過濾器。
FixedHeadAndLengthReceiveFliter:固定開頭和長度的協(xié)議過濾器。
FixedHeadReceiveFliter:固定開頭的協(xié)議過濾器。
FixedLengthReceiveFliter:固定長度的協(xié)議過濾器。
|
這5個(gè)過濾器都繼承自IReceiveFilter接口,也可以繼承這個(gè)接口進(jìn)行二次開發(fā),定制自己的協(xié)議過濾器。代碼工程如下圖:
9.4 設(shè)備驅(qū)動(dòng)開發(fā)注意事項(xiàng)
對于開發(fā)設(shè)備驅(qū)動(dòng),在初始化過程中可以增加這個(gè)驅(qū)動(dòng)的協(xié)議過濾器,代碼如下:
1
2
3
4
5
|
public override void Initialize(string devid)
{
this.Protocol.InitDriver(this.GetType(),new FixedHeadAndEndReceiveFliter(new byte[] {0x55,0xaa},new byte[] {0x0d} ));
……
}
|
9.5 宿主程序服務(wù)實(shí)例配置注意事項(xiàng)
在配置參數(shù)中需要配置:StartReceiveDataFliter = true,協(xié)議過濾器才能起到作用。代碼如下:
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
37
38
39
40
|
static void Main(string[] args)
{
DeviceSelfDriver dev2 = new DeviceSelfDriver();
dev2.DeviceParameter.DeviceName = "網(wǎng)絡(luò)設(shè)備";
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 = "服務(wù)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#通訊(串口和網(wǎng)絡(luò))框架的設(shè)計(jì)與實(shí)現(xiàn)》
2.[開源]C#跨平臺物聯(lián)網(wǎng)通訊框架ServerSuperIO(SSIO)介紹
2.應(yīng)用SuperIO(SIO)和開源跨平臺物聯(lián)網(wǎng)框架ServerSuperIO(SSIO)構(gòu)建系統(tǒng)的整體方案