.NET中應用程序內共享UdpClient聯機的實現方法_.Net教程

      編輯Tag賺U幣

      推薦:基于.NET中建構子中傳遞子對象的對象詳解
      本篇文章介紹了,基于.NET中建構子中傳遞子對象的對象詳解。需要的朋友參考下

      原始碼下載:

      在開發與遠程設備通訊的系統時,為了提高數據傳輸的效率,常常會選擇UDP這個通訊協議來作為數據傳輸的媒介。而 .NET framework中所提供的UdpClient對象,可以幫助開發人員依照系統需求開啟UDP套接字點,快速建立UDP聯機來提供與遠程設備通訊的功能。

      這個系統架構下當增加一個不同種類的遠程設備時,必須要提供一個不同的UDP套接字點,才能用來提供與不同種類遠程設備通訊的功能,在遠程設備種類越來越多時,系統所需要的UDP套接字點就會依照遠程設備種類而增加。

      在遠程設備種類越來越多的情景中,為了網絡管理考慮會限制系統與遠程設備通訊時,必須統一使用同一個UDP套接字點來與遠程設備通訊,再由封包內容、或是IP地址去判斷實際連接的遠程設備為何。

      復制代碼 代碼如下:www.wf0088.com

      class Program
      {
      static void Main(string[] args)
      {
      // Receiver
      UdpClient udpClientA = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

      UdpClient udpClientB = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));
      }
      }

      依照系統需求開發人員可能寫出上列的程序代碼,直接建立兩個UdpClient對象來開啟同一個UDP套接字點。這段程序代碼內容可以通過編譯程序的檢查,但在按下執行之后,就會在Visual Studio之中看到SocketException的例外通知,用來告知開發人員同一個套接字點只能被開啟一次,使用兩個UdpClient來開啟同一個套接字點是無法執行的。

      有涉略過Design pattern的開發人員,在遇到資源對象只能有一個實體的情景,會想到套用Singleton Pattern來提供資源對象共享的功能。系統中UdpClient對象所開啟的UDP套接字點,就是屬于這種只能由一個對象所開啟的資源,這個情景中在UdpClient對象上套用Singleton Pattern看起來會是個不錯的選擇。

      復制代碼 代碼如下:www.wf0088.com

      class Program
      {
      // Singleton
      private static UdpClient _udpClientInstance = null;

      private static UdpClient UdpClientInstance
      {
      get
      {
      if (_udpClientInstance == null)
      {
      _udpClientInstance = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));
      }
      return _udpClientInstance;
      }
      }


      // Main
      static void Main(string[] args)
      {
      // Receiver
      UdpClient udpClientA = Program.UdpClientInstance;

      UdpClient udpClientB = Program.UdpClientInstance;

      // Transmiter
      UdpClient transmiter = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999));


      // Send
      transmiter.Send(new byte[] { 55 }, 1, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));


      // Receive
      byte[] packet = null;
      IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);

      packet = udpClientA.Receive(ref remoteEndPoint);
      Console.WriteLine(string.Format("UdpClientA Receive:{0}", packet[0]));

      packet = udpClientB.Receive(ref remoteEndPoint);
      Console.WriteLine(string.Format("UdpClientB Receive:{0}", packet[0]));

      // End
      Console.ReadLine();

      // Close
      transmiter.Close();
      udpClientB.Close();
      udpClientA.Close();
      }
      }

      將Singleton Pattern套用在系統內所使用的UdpClient物件上,可以寫出上列的程序代碼,系統內所使用的UdpClient對象都是取用到系統內一個靜態存放的共享UdpClient對象。這段程序代碼內容可以通過編譯程序的檢查,并且在執行時也不會出現SocketException的例外通知,因為套用Singleton Pattern讓系統內只會開啟UDP套接字點一次。

      但進階一點去思考UdpClient對象的封包接收功能,UdpClient對象中提供Receive方法來等待、接收遠程設備傳送的數據封包,收到數據封包之后再次執行Receive方法會繼續等待、接收下一個數據封包。也就是說一個遠程設備傳送的數據封包,UdpClient只能透過Receive方法取得一次,在系統內共享同UdpClient對象,沒有辦法共享Receive方法所取得的數據封包。

      觀察上列范例的執行結果,可以發現在范例中由transmiter所傳送的資料封包,在被UdpClientA透過Receive方法接收之后,UdpClientB無法接收到這個遠程傳送的數據封包,這也就驗證范例中將Singleton Pattern套用在系統內所使用UdpClient上的方式,會發生了無法共享數據封包的問題。

      為了提供系統使用同一個UDP套接字點來與遠程設備通訊,再由封包內容、或是IP地址去判斷實際連接的遠程設備為何的功能。筆者設計一個名為MutualUdpClient的解決方案,用來在系統內共享UDP通訊聯機并且共享遠程設備傳送的數據封包。

      在MutualUdpClient這個解決方案中,套用先前部落格中所發表的Singleton Pool模式,套用這個模式讓系統能夠共享UdpClient聯機,并且在有系統對象使用UdpClient聯機時就開啟共享UDP通訊聯機,而在所有系統對象都不需要使用UdpClient聯機才真正去關閉這個共享的UDP通訊聯機。

      套用Singleton Pool模式解決了共享UdpClient聯機的功能,接著在MutualUdpClient這個解決方案中,為了共享遠程設備傳送的數據封包,在UdpClient與MutualUdpClient之間加入了一個RouteUdpClient對象。

      RouteUdpClient對象是一個主動式的對象,在被建立之后會開啟一條獨立的線程,不斷的接收UdpClient所接收到的數據封包,并且將接收到數據封包透過事件的方式通知每個MutualUdpClient,經由這樣的流程就可以將遠程設備所傳送的數據封包,在每個MutualUdpClient之間共享。

      而MutualUdpClient對象在收到RouteUdpClient所提供的數據封包時,會先將數據封包暫存在一個隊列里,并且在MutualUdpClient對象的Receive方法被呼叫時,再從隊列取出數據封包并且回傳給呼叫端,用以將遠程設備傳送的數據封包提供給呼叫端做后續的處理。經由這樣的方式,每個系統中所建立的MutualUdpClient對象就可以透過Receive方法取得,每個遠程設備傳送的數據封包。

      *這邊要特別一提的是,MutualUdpClient對象不選擇事件方式來提供數據封包而采用Receive方法來提供,是為了讓使用MutualUdpClient對象的開發人員,在使用對象的時候,能夠得到與使用UdpClient一樣的開發體驗,用以減少開發時的學習時間。

      處理完共享UdpClient聯機、共享遠程設備傳送的資料封包之后,還要處理一下傳送數據封包到遠程設備的功能。在MutualUdpClient之中,對于傳送數據封包到遠程設備并沒有特殊需求,所以直接使用UdpClient的Send功能就可以完成將數據封包傳送到遠程設備的功能。

      復制代碼 代碼如下:www.wf0088.com

      class Program
      {
      static void Main(string[] args)
      {
      // Receiver
      MutualUdpClient udpClientA = new MutualUdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

      MutualUdpClient udpClientB = new MutualUdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

      // Transmiter
      UdpClient transmiter = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999));


      // Send
      transmiter.Send(new byte[] { 55 }, 1, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));


      // Receive
      byte[] packet = null;
      IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);

      packet = udpClientA.Receive(ref remoteEndPoint);
      Console.WriteLine(string.Format("UdpClientA Receive:{0}", packet[0]));

      packet = udpClientB.Receive(ref remoteEndPoint);
      Console.WriteLine(string.Format("UdpClientB Receive:{0}", packet[0]));

      // End
      Console.ReadLine();

      // Close
      transmiter.Close();
      udpClientB.Close();
      udpClientA.Close();
      }
      }

      上列程序代碼示范如何在系統中使用MutualUdpClient對象,在范例中可以看到程序代碼中直接建立了兩個相同UDP端點的MutualUdpClient對象,并且可以正常的執行不會出現SocketException的例外通知。而遠程設備transmiter所傳送的數據封包,在被UdpClientA透過Receive方法接收之后,UdpClientB依然可以透過Receive方法接收同一個資料,這也就驗證了MutualUdpClient對象提供了共享通訊聯機、共享數據封包的功能。

      原始碼下載:

      分享:.NET中STAThread的使用詳解
      這個STA線程模型,在線程內加入了訊息幫浦等等機制,減少開發人員撰寫窗口程序的工作量

      來源:模板無憂//所屬分類:.Net教程/更新時間:2013-05-05
      相關.Net教程