目       錄

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. 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è)問題,如下圖:

  1. 2.      粘包及解決

    我原來并不知道粘包這個(gè)概念,后來在網(wǎng)上看文章才明白。在通訊領(lǐng)域中也是經(jīng)常會遇到的問題。也就是多包數(shù)據(jù)一次性的接收,那么就要合理的進(jìn)行拆包。還有一種情況,就是多包半的數(shù)據(jù)一次性的接收,那半包的數(shù)據(jù)結(jié)合“1.一包多發(fā)及解決”來解決這個(gè)問題,示意如下圖:

 

    ServerSuperIO設(shè)置了協(xié)議過濾器,可以解決這個(gè)問題,如下圖:

  1. 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)的整體方案

3.C#工業(yè)物聯(lián)網(wǎng)和集成系統(tǒng)解決方案的技術(shù)路線(數(shù)據(jù)源、數(shù)據(jù)采集、數(shù)據(jù)上傳與接收、ActiveMQ、Mongodb、WebApi、手機(jī)App)