天天看點

C#網絡程式設計系列七:UDP程式設計補充

上次因為時間的關系,是以把上一個專題遺留下的一個問題在本專題中和大家分享下,本專題主要介紹下如何實作UDP廣播的程式,下面就直接介紹實作過程和代碼以及運作的結果。

上次因為時間的關系,是以把上一個專題遺留下的一個問題在本專題中和大家分享下,本專題主要介紹下如何實作UDP廣播的程式,下面就直接介紹實作過程和代碼以及運作的結果。

一、程式實作

UDP廣播程式的實作代碼:

  1. using System;  
  2. using System.Net;  
  3. using System.Net.Sockets;  
  4. using System.Text;  
  5. using System.Threading;  
  6. using System.Windows.Forms;  
  7. namespace UDPBroadcast  
  8. {  
  9.     /// <summary>  
  10.     /// 在界面上,使用者可以設定本地程序的IP位址和端口号,并将位址加入某個多點傳播組;  
  11.     /// 可以輸入發送消息的目的組的位址,并且勾選“廣播”複選框将采用廣播的方式發送資訊  
  12.     /// 在界面上點選“接受按鈕”就啟動接收線程,這樣程式就可以接收廣播或多點傳播的資訊  
  13.     /// </summary>  
  14.     public partial class UdpBroadcasefrm : Form  
  15.     {  
  16.         private UdpClient sendUdpClient;  
  17.         private UdpClient receiveUdpClient;  
  18.         // 多點傳播IP位址  
  19.         IPEndPoint broadcastIpEndPoint;  
  20.         public UdpBroadcasefrm()  
  21.         {  
  22.             InitializeComponent();  
  23.             IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());  
  24.             tbxlocalip.Text = ips[5].ToString();  
  25.             tbxlocalport.Text = "8002";  
  26.             // 預設組,多點傳播位址是有範圍  
  27.             // 具體關于多點傳播和廣播的介紹參照我上一篇部落格UDP程式設計  
  28.             // 本地多點傳播組  
  29.             tbxGroupIp.Text = "224.0.0.1";  
  30.             // 發送到的多點傳播組  
  31.             tbxSendToGroupIp.Text = "224.0.0.1";  
  32.         }  
  33.         // 設定加入組  
  34.         private void chkbxJoinGtoup_Click(object sender, EventArgs e)  
  35.         {  
  36.             if (chkbxJoinGtoup.Checked == true)  
  37.             {  
  38.                 tbxGroupIp.Enabled = false;  
  39.             }  
  40.             else 
  41.             {  
  42.                 tbxGroupIp.Enabled = true;  
  43.                 tbxGroupIp.Focus();  
  44.             }  
  45.         }  
  46.         // 選擇發送模式後設定  
  47.         private void chkbxBroadcast_Click(object sender, EventArgs e)  
  48.         {  
  49.             if (chkbxBroadcast.Checked == true)  
  50.             {  
  51.                 tbxSendToGroupIp.Enabled = false;  
  52.             }  
  53.             else 
  54.             {  
  55.                 tbxSendToGroupIp.Enabled = true;  
  56.                 tbxSendToGroupIp.Focus();  
  57.             }  
  58.         }  
  59.         // 發送消息  
  60.         private void btnSend_Click(object sender, EventArgs e)  
  61.         {  
  62.             if (tbxMessageSend.Text == "")  
  63.             {  
  64.                 MessageBox.Show("消息内容不能為空!","提示");  
  65.                 return;  
  66.             }  
  67.             // 根據選擇的模式發送資訊  
  68.             if (chkbxBroadcast.Checked == true)  
  69.             {  
  70.                 // 廣播模式(自動獲得子網中的IP廣播位址)  
  71.                 broadcastIpEndPoint = new IPEndPoint(IPAddress.Broadcast, 8002);  
  72.             }  
  73.             else 
  74.             {  
  75.                 // 多點傳播模式  
  76.                 broadcastIpEndPoint = new IPEndPoint(IPAddress.Parse(tbxSendToGroupIp.Text), 8002);  
  77.             }  
  78.             // 啟動發送線程發送消息  
  79.             Thread sendThread = new Thread(SendMessage);  
  80.             sendThread.Start(tbxMessageSend.Text);  
  81.         }  
  82.         // 發送消息  
  83.         private void SendMessage(object obj)  
  84.         {  
  85.             string message = obj.ToString();  
  86.             byte[] messagebytes = Encoding.Unicode.GetBytes(message);  
  87.             sendUdpClient = new UdpClient();  
  88.             // 發送消息到多點傳播或廣播位址  
  89.             sendUdpClient.Send(messagebytes, messagebytes.Length, broadcastIpEndPoint);  
  90.             sendUdpClient.Close();  
  91.             // 清空編輯消息框  
  92.             ResetMessageText(tbxMessageSend);  
  93.         }  
  94.         // 利用委托回調機制來實作界面上的消息清空操作  
  95.         delegate void ResetMessageTextCallBack(TextBox textbox);  
  96.         private void ResetMessageText(TextBox textbox)  
  97.         {  
  98.             if (textbox.InvokeRequired)  
  99.             {  
  100.                 ResetMessageTextCallBack resetMessageCallback = ResetMessageText;  
  101.                 textbox.Invoke(resetMessageCallback, new object[] { textbox });  
  102.             }  
  103.             else 
  104.             {  
  105.                 textbox.Clear();  
  106.                 textbox.Focus();  
  107.             }  
  108.         }  
  109.         // 接收消息  
  110.         private void btnReceive_Click(object sender, EventArgs e)  
  111.         {  
  112.             chkbxJoinGtoup.Enabled = false;  
  113.             // 建立接收套接字  
  114.             IPAddress localIp = IPAddress.Parse(tbxlocalip.Text);  
  115.             IPEndPoint localIpEndPoint = new IPEndPoint(localIp, int.Parse(tbxlocalport.Text));  
  116.             receiveUdpClient = new UdpClient(localIpEndPoint);  
  117.             // 加入多點傳播組  
  118.             if (chkbxJoinGtoup.Checked == true)  
  119.             {  
  120.                 receiveUdpClient.JoinMulticastGroup(IPAddress.Parse(tbxGroupIp.Text));  
  121.                 receiveUdpClient.Ttl = 50;  
  122.             }  
  123.             // 啟動接受線程  
  124.             Thread threadReceive = new Thread(ReceiveMessage);  
  125.             threadReceive.Start();  
  126.         }  
  127.         // 接受消息方法  
  128.         private void ReceiveMessage()  
  129.         {  
  130.             IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);  
  131.             while (true)  
  132.             {  
  133.                 try 
  134.                 {  
  135.                     // 關閉receiveUdpClient時此時會産生異常  
  136.                     byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIpEndPoint);  
  137.                     string receivemessage = Encoding.Unicode.GetString(receiveBytes);  
  138.                     // 顯示消息内容  
  139.                     ShowMessage(lstMessageBox, string.Format("{0}[{1}]", remoteIpEndPoint, receivemessage));  
  140.                 }  
  141.                 catch 
  142.                 {  
  143.                     break;  
  144.                 }  
  145.             }  
  146.         }  
  147.         // 通過委托回調機制顯示消息内容  
  148.         delegate void ShowMessageCallBack(ListBox listbox,string text);  
  149.         private void ShowMessage(ListBox listbox, string text)  
  150.         {  
  151.             if (listbox.InvokeRequired)  
  152.             {  
  153.                 ShowMessageCallBack showmessageCallback = ShowMessage;  
  154.                 listbox.Invoke(showmessageCallback, new object[] { listbox, text });  
  155.             }  
  156.             else 
  157.             {  
  158.                 listbox.Items.Add(text);  
  159.                 listbox.SelectedIndex = listbox.Items.Count - 1;  
  160.                 listbox.ClearSelected();  
  161.             }  
  162.         }  
  163.         // 清空消息清單  
  164.         private void btnClear_Click(object sender, EventArgs e)  
  165.         {  
  166.             lstMessageBox.Items.Clear();  
  167.         }  
  168.         // 停止接收  
  169.         private void btnStop_Click(object sender, EventArgs e)  
  170.         {  
  171.             chkbxJoinGtoup.Enabled =true;  
  172.             receiveUdpClient.Close();  
  173.         }    
  174.     }  

廣播示範結果(接收端直接點接收按鈕後開啟接受線程,在發送端勾選“廣播選項”輸入發送資訊點發送按鈕後的界面如下):

C#網絡程式設計系列七:UDP程式設計補充

下面通過把接收端加入組後的結果,首先終止接收線程,然後勾選“加入組”複選框,然後單擊“接收”按鈕重新開啟接收線程,輸出結果如下:

C#網絡程式設計系列七:UDP程式設計補充

從廣播示範的兩個情況可以看出廣播消息會同時向網上的一切程序轉發,無論這個程序是獨立的還是加入了某個多點傳播組中的程序,都可以接收廣播消息

下面示範下多點傳播的結果:

C#網絡程式設計系列七:UDP程式設計補充

如果把接收端的組位址改為224.0.0.3時,此時發送端發送的消息“多點傳播示範2”将不會發送到不同的多點傳播位址,則接收端就接收不到此時的消息。

從多點傳播結果中可以看出隻有加入多點傳播位址224.0.0.2的程序才能接收到資訊。

需要注意的地方是:從前面的截圖中可以看出,不論是廣播還是多點傳播,僅僅從收到的資訊無從知道發送給它的程序的端口号,是以廣播群組播消息都是匿名發送,并且通過對UDP廣播群組播的了解可以簡單實作一個消息群發的功能(QQ的群裡聊天就是這個原理)。

二、 總結

本專題主要是針對上一專題的補充——實作一個簡單的UDP廣播(多點傳播)程式,通過這樣一個發送端可以發送給在多點傳播位址中的所有使用者和所有子網中的所有使用者。本專題可以說是對UDP程式設計的一個擴充吧,希望大家看了本專題後可以對UDP協定有大緻的了解。在下一個專題中會和大家介紹下P2P程式設計的相關知識。

全部源碼位址:http://files.cnblogs.com/zhili/UDPBroadcast.zip

原文連結:http://www.cnblogs.com/zhili/archive/2012/09/03/UDPBroadcas.html