程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> [更新設計]跨平台物聯網通訊框架ServerSuperIO 2.0 ,功能、BUG、細節說明,以及升級思考過程!,serversuperiobug

[更新設計]跨平台物聯網通訊框架ServerSuperIO 2.0 ,功能、BUG、細節說明,以及升級思考過程!,serversuperiobug

編輯:C#入門知識

[更新設計]跨平台物聯網通訊框架ServerSuperIO 2.0 ,功能、BUG、細節說明,以及升級思考過程!,serversuperiobug


     注:ServerSuperIO 2.0 還沒有提交到開源社區,在內部測試!!!

1. ServerSuperIO(SSIO)說明

     SSIO是基於早期工業現場300波特率通訊傳輸應用場景發展、演化而來。為了適應互聯網、物聯網的發展趨勢,以及不同應用場景的需求,SSIO也在不斷的進行更新。

     SSIO是一個跨平台的物聯網通訊框架,但是其本質不僅僅是通訊框架,而是設備驅動、串口和網絡IO管理器、場景控制器三者之間的協調與調度機制。

物聯網是一個發展趨勢,如果各種傳感器、硬件設備的協議驅動無法統一,那麼使用SSIO框架來開發設備驅動,隨意掛載到框架運行並且進行通訊和交互,你擁有的是集成能力,以及對用戶的承諾;如果是公司內部使用,協議是“標准”的,那麼使用SSIO更簡單、方便,降低人員成本、提高生產效率。

2. 升級概要

1.1  功能

1.在串口和網絡IO中增加接收數據緩存功能,充分利用緩存空間,保證數據的完整性。

2.修改數據分發策略,現在以遠程IP或設備編號兩種方式分發數據。

3.增加接收數據過濾器,保證數據按一定的規則進行提取,以及保證數據的連續性。

4.增加定時、超時清理網絡連接資源,如果網絡連接在一定時間范圍內沒有接到數據,則進行清理。

5.其他代碼優化。

1.2 BUG

1.修復:退出軟件可能造成的異常。

2.修復:分發數據的邏輯問題。

1.3 細節

1.在協議驅動IProtocolDriver增加GetCode和GetPackageLength接口。GetCode一般為設備的唯一編號;GetPackageLength一般獲得本次數據包應該接收的數據長度,在框架中並未實際使用。

2.把CommandCache命令空間改為DataCache,下面增加ISendCache發送緩存接口和IReceiveCache接收緩存接口。
3.把現在設備驅動中的CommandCache改為SendCache發送數據緩存,移植到ProtocolDriver協議驅動中。
4.在ComSession和TcpSocketSession中增加ReceiveCache接收數據緩存。
5.增加IReceiveFilter接收數據過濾器接口。
7.去掉按設備地址分發數據,增加按設備編碼分發數據。
8.網絡偵聽連接的時候,退出軟件有可能造成異常。
9.網絡異步接收數據時,在邏輯上有可能造成分發錯誤。
10.對配置文件進行修改,增加StartReceiveDataFliter、ClearSocketSession、ClearSocketSessionInterval和ClearSocketSessionTimeOut。
11.網絡通訊時,去掉多少次沒有接收到數據進行清理連接的功能。

 

3. 升級考慮

3.1  設備/傳感器編碼

      SSIO原來是用設備地址(DeviceAddress)來識別設備驅動,而DeviceAddress是int類型,不能滿足業務場景的需求了,因為設備編碼不僅僅是一個數字類型的數值,有可能是一串字符串,包括數字和字母。設備編碼包括設備地址,是識別設備的一個規則編碼。有時候設備編碼與設備地址是等同的。

      所以在設備驅動中增加了GetCode接口,這個接口也作為網絡異步接收數據使用過濾器查找設備的接口,一般需要在配置文件設備StartReceiveDataFliter屬性。

      GetCode可以進行模糊查找,並且返回設備編碼,如下代碼:

public override string GetCode(byte[] data)
{
            int codeIndex = -1;
            byte[] head=new byte[] {0x55,0xaa};
            for (int i = 0; i < data.Length; i++)
            {
                if (data.Mark(0, data.Length, i, head))
                {
                    codeIndex = i;
                    break;
                }
            }

            if (codeIndex == -1)
            {
                return String.Empty;
            }
            else
            {
                return data[codeIndex + head.Length].ToString("00#");
            }
}

 3.2  接收數據緩存

     SSIO以前接收完數據,直接從緩存中提取數據後返回給了設備驅動;也有另外一種方案,就是創建一個更大的緩存對象保存byte數據,但是這種方案有些浪費內存空間,以及效率。

     SSIO現在采用了折中方案,利用現有的緩存空間(byte[]),配合接收數據過濾器,對已經接收到的數據進行管理和過濾提取,並且對未提取的數據有持久存儲的能力。代碼如下:

/// <summary>
/// 獲得數據
/// </summary>
 /// <param name="filter"></param>
public IList<byte[]> Get(IReceiveFilter filter)
{
            if (filter == null)
            {
                throw new NullReferenceException("filter引用為空");
            }

            if (DataLength <= 0)
            {
                return new List<byte[]>();
            }

            lock (_SyncLock)
            {
                int lastByteOffset = InitOffset;
                IList<byte[]> listBytes = filter.Filter(ReceiveBuffer, InitOffset, DataLength, ref lastByteOffset);
                if (listBytes != null 
                    && listBytes.Count > 0
                    && lastByteOffset>InitOffset)
                {
                    CurrentOffset = lastByteOffset + 1;

                    int gets = CurrentOffset - InitOffset ;
                    DataLength -= gets;

                    MoveLeft(gets);
                }
                return listBytes;
            }
 }

3.3  接收數據過濾器

    接收數據過濾器是按一定的原則在數據緩存中查找、提取數據信息,過濾器接口定義如下代碼:

/// <summary>
 /// 過濾數據信息
 /// </summary>
/// <param name="receiveBuffer">緩沖區</param>
 /// <param name="offset">偏移量</param>
 /// <param name="length">有效數據長度</param>
 /// <param name="lastByteOffset">最後一個字節的偏移量</param>
 /// <returns>沒有數據返回null</returns>
 IList<byte[]> Filter(byte[] receiveBuffer, int offset, int length, ref int lastByteOffset);

    SSIO在此接口的基礎上,實現了5種數據過濾方式,固定結尾的方式(FixedEndReceiveFliter)、固定開頭和結尾的方式(FixedHeadAndEndReceiveFliter)、因定開頭的方式(FixedHeadReceiveFliter)、固定開頭和長度的方式(FixedHeadAndLengthReceiveFliter)、因定長度的方式(FixedLengthReceiveFliter),這幾種方式各有利弊,請根據不同設備的協議使用不同的過濾器。

3.4 定時檢測,超時清理網絡連接

      SSIO以前是設置一個發送和接收次數值,如果超過這個值,還沒有接收到數據信息,那麼就認為是失效的IO通道,就會關閉、釋放掉資源。

      SSIO現在增加了定時檢測功能,如果在一定時間范圍內(可設備)還沒有接收到數據,那麼就認為是失效的IO通道,就會關閉、釋放掉資源。代碼如下:

private void ClearSocketSession(object state)
 {
            if (Monitor.TryEnter(state))
            {
                try
                {
                    ICollection<IChannel> socketChannels = this.ChannelManager.GetChannels(CommunicateType.NET);

                    if (socketChannels == null || socketChannels.Count<=0)
                        return;

                    DateTime now = DateTime.Now;
  
                    IEnumerable<IChannel> timeoutSessions = socketChannels.Where(c => (now-((ISocketSession)c).LastActiveTime).Seconds>Config.ClearSocketSessionTimeOut);

                    System.Threading.Tasks.Parallel.ForEach(timeoutSessions, c =>
                    {
                       ISocketSession s = ((ISocketSession) c);
                       Logger.Info(true,String.Format("網絡連接超時:{0}, 開始時間: {1}, 最後激活時間:{2}!", now.Subtract(s.LastActiveTime).TotalSeconds, s.StartTime, s.LastActiveTime));
                        RemoveTcpSocketSession(s);
                    });
                }
                catch (Exception ex)
                {
                    this.Logger.Error(true,ex.Message);
                }
                finally
                {
                    Monitor.Exit(state);
                }
            }
}

3.5 數據分發原則

    對於輪詢模式通訊,不存在數據分發,因為每次高度設備驅動,都是順序執行發送和接收操作,接收的數據肯定是這個設備驅動的,就會立即返回。

    但是對於並發模式、自主模式、單例模式的通訊方式(應用場景),是異步接收數據信息,我怎麼知道接收過來的數據應該分配哪個設備驅動呢?有兩種方式:按IP和按設備編碼(原來是按數字類型的設備地址)。接收到的數據,會通過設備協議驅動與設備參數進行比對,並且進行數據分發。如下代碼:

/// <summary>
  /// 分發數據模式
  /// </summary>
    public enum DeliveryMode
    {
        [EnumDescription("設備IP分發數據")]
        DeviceIP,
        [EnumDescription("設備編碼分發數據")]
        DeviceCode
    }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved