詳解基於C#的UDP協議的同步通訊的範例程式碼

來源:互聯網
上載者:User
本篇文章主要介紹了基於C#的UDP協議的同步實現代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、摘要

總結基於C#的UDP協議的同步通訊。

二、實驗平台

Visual Studio 2010

三、實驗原理

UDP傳輸協議同TCP傳輸協議的區別可查閱相關文檔,此處不再贅述。

四、執行個體

4.1 採用socket實現UDP

由於UDP是一種不需連線的協議。因此,為了使伺服器應用能夠發送和接收UDP資料包,則需要做兩件事情:

(1) 建立一個Socket對象;

(2) 將建立的通訊端對象與本地IPEndPoint進行綁定。

完成上述步驟後,那麼建立的通訊端就能夠在IPEndPoint上接收流入的UDP資料包,或者將流出的UDP資料包發送到網路中其他任意裝置。使用UDP進行通訊時,不需要串連。因為異地的主機之間沒有建立串連,所以UDP不能使用標準的Send()和Receive()t通訊端方法,而是使用兩個其他的方法:SendTo()和ReceiveFrom()。

SendTo()方法指定要發送的資料,和目標機器的IPEndPoint。該方法有多種不同的使用方法,可以根據具體的應用進行選擇,但是至少要指定資料包和目標機器。如下:

SendTo(byte[] data,EndPoint Remote)

ReceiveFrom()方法同SendTo()方法類似,但是使用EndPoint對象聲明的方式不一樣。利用ref修飾,傳遞的不是一個EndPoint對象,而是將參數傳遞給一個EndPoint對象。

UDP應用不是嚴格意義上的真正的伺服器和客戶機,而是平等的關係,即沒有主與次的關係。為了簡便起見,仍然把下面的這個應用叫做UDP伺服器。

伺服器端代碼:

using System;using System.Collections.Generic;using System.Text;using System.Net;using System.Net.Sockets;namespace UDP{ class Program {  static void Main(string[] args)  {   int recv;   byte[] data = new byte[1024];   //得到本機IP,設定TCP連接埠號碼      IPEndPoint ip = new IPEndPoint(IPAddress.Any, 8001);   Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);   //綁定網路地址   newsock.Bind(ip);   Console.WriteLine("This is a Server, host name is {0}", Dns.GetHostName());   //等待客戶機串連   Console.WriteLine("Waiting for a client");   //得到客戶機IP   IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);   EndPoint Remote = (EndPoint)(sender);   recv = newsock.ReceiveFrom(data, ref Remote);   Console.WriteLine("Message received from {0}: ", Remote.ToString());   Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));   //客戶機串連成功後,發送資訊   string welcome = "你好 ! ";   //字串與位元組數組相互轉換   data = Encoding.ASCII.GetBytes(welcome);   //發送資訊   newsock.SendTo(data, data.Length, SocketFlags.None, Remote);   while (true)   {    data = new byte[1024];    //發送接收資訊    recv = newsock.ReceiveFrom(data, ref Remote);    Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));    newsock.SendTo(data, recv, SocketFlags.None, Remote);   }  } }}

對於接收流入的UDP伺服器程式來說,必須將程式與本地系統中指定的UDP連接埠進行綁定。這就可以通過使用合適的本地IP地址建立一個IPEndPoint對象,以及合適的UDP連接埠號碼。上述範常式序中的UDP伺服器能夠在連接埠8001從網路上接收任意流入的UDP資料包。

UDP客戶機程式與伺服器程式非常類似。

因為客戶機不需要在指定的UDP連接埠等待流入的資料,因此,不使用Bind()方法,而是使用在資料發送時系統隨機指定的一個UDP連接埠,而且使用同一個連接埠接收返回的訊息。在開發產品時,要為客戶機指定一套UDP連接埠,以便伺服器和客戶機程式使用相同的連接埠號碼。UDP客戶機程式首先定義一個IPEndPoint,UDP伺服器將發送資料包到這個IPEndPoint。如果在遠程裝置上運行UDP伺服器程式,在IPEndPoint定義中必須輸入適當的IP地址和UDP連接埠號碼資訊。

用戶端代碼:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace UDPClient{ class Program {  static void Main(string[] args)  {   byte[] data = new byte[1024];   string input, stringData;   //構建TCP 伺服器   Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());   //設定服務IP,設定TCP連接埠號碼   IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);   //定義網路類型,資料連線類型和網路通訊協定UDP   Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);   string welcome = "你好! ";   data = Encoding.ASCII.GetBytes(welcome);   server.SendTo(data, data.Length, SocketFlags.None, ip);   IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);   EndPoint Remote = (EndPoint)sender;   data = new byte[1024];   //對於不存在的IP地址,加入此行代碼後,可以在指定時間內解除阻塞模式限制   int recv = server.ReceiveFrom(data, ref Remote);   Console.WriteLine("Message received from {0}: ", Remote.ToString());   Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));   while (true)   {    input = Console.ReadLine();    if (input == "exit")     break;    server.SendTo(Encoding.ASCII.GetBytes(input), Remote);    data = new byte[1024];    recv = server.ReceiveFrom(data, ref Remote);    stringData = Encoding.ASCII.GetString(data, 0, recv);    Console.WriteLine(stringData);   }   Console.WriteLine("Stopping Client.");   server.Close();  } }}

上述代碼的實現邏輯為:相關設定完成後,伺服器端先向用戶端發送資訊,之後用戶端通過鍵盤發送字串,伺服器端收到後再發送給用戶端,如此迴圈。

4.2 採用UDPClient類實現

伺服器端代碼:

using System;using System.Net;using System.Net.Sockets;using System.Text;public class Custom{ // 設定IP,IPV6 private static readonly IPAddress GroupAddress = IPAddress.Parse("IP地址"); // 設定連接埠 private const int GroupPort = 11000; private static void StartListener() {  bool done = false;  UdpClient listener = new UdpClient();  IPEndPoint groupEP = new IPEndPoint(GroupAddress, GroupPort);  try  {   //IPV6,組播   listener.JoinMulticastGroup(GroupAddress);   listener.Connect(groupEP);   while (!done)   {    Console.WriteLine("Waiting for broadcast");    byte[] bytes = listener.Receive(ref groupEP);    Console.WriteLine("Received broadcast from {0} :\n {1}\n", groupEP.ToString(), Encoding.ASCII.GetString(bytes, 0, bytes.Length));   }   listener.Close();  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } public static int Main(String[] args) {  StartListener();  return 0; }}

用戶端代碼:

using System;using System.Net;using System.Net.Sockets;using System.Text;public class Client{ private static IPAddress GroupAddress = IPAddress.Parse("IP地址"); private static int GroupPort = 11000; private static void Send(String message) {  UdpClient sender = new UdpClient();  IPEndPoint groupEP = new IPEndPoint(GroupAddress, GroupPort);  try  {   Console.WriteLine("Sending datagram : {0}", message);   byte[] bytes = Encoding.ASCII.GetBytes(message);   sender.Send(bytes, bytes.Length, groupEP);   sender.Close();  }  catch (Exception e)  {   Console.WriteLine(e.ToString());  } } public static int Main(String[] args) {  Send(args[0]);  return 0; }}

以上代碼需要說明的是:

(1) 上述代碼是基於IPV6地址的組播模式。IPv4中的廣播(broadcast)可以導致網路效能的下降甚至廣播風暴(broadcast storm)。在IPv6中就不存在廣播這一概念了,取而代之的是組播(multicast)和任意播(anycast)。

(2) IPV6地址表示方法:

a) X:X:X:X:X:X:X:X(每個X代表16位的16進位數字),不區分大小寫;

b) 排頭的0可省略,比如09C0就可以寫成9C0,0000可以寫成0;

c) 連續為0的欄位可以以::來代替,但是整個地址中::只能出現一次,比如FF01:0:0:0:0:0:0:1就可以簡寫成FF01::1。

(3) 如果是採用表單的形式建議使用這種格式,否則在接收資料時可能會出現死機的現象。

// 建立一個子線程   Thread thread = new Thread(    delegate()    {     try     {      //在這裡寫你的代碼     }     catch (Exception )     {     }    }   );   thread.Start();
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.