程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> [連載]《C#通訊(串口和網絡)框架的設計與實現》- 6.通訊控制器的設計,

[連載]《C#通訊(串口和網絡)框架的設計與實現》- 6.通訊控制器的設計,

編輯:C#入門知識

[連載]《C#通訊(串口和網絡)框架的設計與實現》- 6.通訊控制器的設計,


目       錄

第六章           通訊控制器的設計... 2

6.1           控制器接口... 2

6.2           串口控制器... 3

6.3           網絡控制器... 5

6.4           通訊控制管理器... 9

6.5           遠程交互... 9

6.6           小結... 10

 

第六章     通訊控制器的設計

     經過前幾章的介紹,這章介紹通訊控制器。主要負責對設備驅動(IRunDevice)、IO通道(IIOChannel)進行協調、調度、以及事件做出響應,在此基礎上實現輪詢通訊模式、並發通訊模式和自控通訊模式的任務調度。由於串口和網絡硬件鏈路特性的原因以及通訊機制不一樣,所以通訊控制器的實現上也有很大差別。

6.1    控制器接口

     控制器內置一個線程負責對設備驅動和IO實例進行任務協調、調度,相當於在《第4章 設備管理器的設計》、《第5章 串口和網絡的IO設計》實現的基礎上構建了一個更高層次的協調機制,並實現設備與IO的匹配、不同的通訊機制。

     不管串口通訊控制器和網絡通訊控制器如何實現,都會繼承自統一的(IIOController)接口,接口定義的代碼如下:

public interface IIOController
{
       /// <summary>
       /// 當然是否工作
       /// </summary>
       bool IsWorked { set; get; }

       /// <summary>
       /// IO控制器的關鍵字。
       /// </summary>
       string Key { get; }

       /// <summary>
       /// 啟動服務
       /// </summary>
       void StartService();

       /// <summary>
       /// 停止服務
       /// </summary>
       void StopService();

       /// <summary>
       /// IO控制器類型
       /// </summary>
       CommunicationType ControllerType { get; }
}

     控制層次結構圖如下:

 

6.2    串口控制器

    每個(硬件)串口都對應一個串口控制器,每個串口控制器裡都會有一個獨立的線程,也就是說用到多少個串口號就會有多少個控制器和線程。框架平台可能會掛載多個設備驅動(插件),有可能一個設備驅動對應一個串口,也可能幾個設備驅動共用一個串口,那麼也就是說串口控制器和設備驅動之間存在1對1或1對N的關系。結構示意圖如下:

 某個設備調度周期=(串口控制器所有設備數-1)* 單個設備驅動執行耗時

      這僅是一個理論值,實際應用中要比這個理論值要大,因為涉及到不類型的設備驅動共用一個串口號,在一個串口控制器下工作,處理的數據流程、方式不同,例如:有可能數據保存在TXT文件中、有可能保存在SQL數據庫中、有可能保存在NoSQL數據庫中等等。

     有人會想,豈不是在一個串口下掛載的設備越多效率越低,的確是這樣的。但是,多個串口控制器之間是並行工作模式。如果現場環境對通訊效率有要求的話,可以增加串口服務器,也就是增加可用的串口硬件電路,把N個設備驅動平衡負載到不同的串口上,增加並行運行的串口控制器的節點,進而提高框架平台的運行效率。

    但是,這樣解決之後也帶來一定的風險和瓶頸,就是對於數據的存儲,如果多個並行的數據流同時向一個單線程的存儲介質寫數據,那麼又會造成互斥的現象,甚至造成意想不到的結果或異常,如下圖:

 

     如果同時向Sql Server、Oracle、Mysql等數據庫存儲數據,那麼是沒有問題的;如果采用文本文件、桌面數據庫等存儲數據,那麼可能存在問題,可以分多個文件進行保存操作。DCS系統大多采用PI(Plant Information System)數據庫。總之,作為一個系統來講,需要整體設計、考慮,這塊需要特別注意。

6.3    網絡控制器

     框架平台只有一個網絡控制器,網絡控制器內有一個獨立的線程負責對所有網絡設備驅動進行輪詢、並發、自控模式通訊調度。輪詢通訊模式與串口控制器類似,只是串行的調度所有網絡設備驅動,但是框架只有一個網絡控制器,不能通過增加網絡控制器來提高通訊效率,這種模式是網絡通訊調度雞肋;並發通訊模式,線程會通過控制器中的線程集中發送所有設備的請求命令數據,接收數據是通過IO異步監聽來完成,異步接收到數據後再把數據分發到設備驅動的RunIODevice接口,進行數據處理;自控通訊模式,發送命令數據的職能移交給了設備驅動本身,可以通過定時器來完成發送命令數據的功能,線程不再負責發送命令數據,接收數據與並發通訊模式一樣。網絡控制器的內部示意圖如下:

 public void ControllerSend(IRunDevice dev, byte[] data) { int counter = DeviceManager.GetInstance().GetCounter(dev.DeviceParameter.DeviceID.ToString()); int sendNum = SessionSocketManager.GetInstance().Send(dev.DeviceParameter.NET.RemoteIP, data); if (sendNum == data.Length && sendNum != 0) { DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, "發送請求數據"); Interlocked.Increment(ref counter); } else { Interlocked.Increment(ref counter); DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, "嘗試發送數據失敗"); } dev.ShowMonitorIOData(data, "發送"); if (counter >= 3) { try { dev.RunIODevice(new byte[] { }); } catch (Exception ex) { DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, ex.Message); GeneralLog.WriteLog(ex); } Interlocked.Exchange(ref counter, 0); } DeviceManager.GetInstance().SetCounter(dev.DeviceParameter.DeviceID.ToString(), counter); }

     異步接收、分數據的代碼如下:

private void NETDeviceController_ReceiveSocketData(object source, ReceiveSocketDataArgs e)
{
       if (GlobalProperty.GetInstance().ControlMode == ControlMode.Parallel || GlobalProperty.GetInstance().ControlMode == ControlMode.Self)
       {
              int counter = 0;
              IRunDevice dev = null;
              IRunDevice[] list = DeviceManager.GetInstance().GetDevices(e.RemoteIP, CommunicationType.NET);
              for (int i = 0; i < list.Length; i++)
              {
                     dev = list[i];
                     if (String.CompareOrdinal(dev.DeviceParameter.NET.RemoteIP, e.RemoteIP) == 0)
                     {
                            dev.ShowMonitorIOData(e.ReceiveData, "接收");
                            dev.AsyncRunIODevice(e.ReceiveData);
                            counter = DeviceManager.GetInstance().GetCounter(dev.DeviceParameter.DeviceID.ToString());
                            Interlocked.Decrement(ref counter);
                            if (counter < 0)
                            {
                                   Interlocked.Exchange(ref counter, 0);
                            }                  DeviceManager.GetInstance().SetCounter(dev.DeviceParameter.DeviceID.ToString(), counter);
                     }
              }
       }
}

6.4    通訊控制管理器

    通訊控制管理器負責對串口控制器和網絡控制器進行管理,實際上是對Dictionary<Key,Value>進行的封裝,所有涉及到操作控制器的地方都是通過控制管理器來完成的。IIOControllerManager<TKey, TValue>通訊控制管理器的接口定義如下:

 

6.5    遠程交互

     在了解串口控制器和網絡控制器的基本原理和功能後,還要考慮到一個應用場景:控制器不僅僅要與硬件進行數據交互,還有可能要把采集上來的數據轉發到其他服務器或節點上,也就是框架平台要具備路由的功能,整合設備驅動采集上來的數據,進行打包、轉發。

    從這個應用場景來看,在開發設備驅動的時候,不適合在設備驅動的處理流程中進行轉發、多業務處理,受環境、網絡、業務復雜度的影響可能會阻塞控制器的調度,影響框架的整體運行效率。

    在物聯網建設中,多級互聯、逐層轉發是很常見技術需求。為了解決這個現實問題,框架平台提供了IAppService應用服務接口,二次開發者可以把設備驅動中的數據信息封裝後傳入到IAppService接口中,可以在這裡實現緩存、轉發等具體的業務服務。這樣設計的主要目的是不影響框架平台實時的數據采集,保證數據源的穩定性。

    IAppService具體的設計和應用將來《第7章 外部接口的設計》中進行詳細介紹。

6.6    小結

     通訊控制器實現這後,理論上框架平台就能夠跑起來了,但是距離我們開始設計的目標還差很多工作要做,還不能為二次開發提供很大的便利。在後續的設計中,慢慢的會把框架平台豐富起來。

 

作者:唯笑志在

Email:[email protected]

QQ:504547114

.NET開發技術聯盟:54256083

文檔下載:http://pan.baidu.com/s/1pJ7lZWf

官方網址:http://www.bmpj.net

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