上次由於時間的關係,因此把上一個專題遺留下的一個問題在本專題中和你們分享下,本專題主要介紹下如何實現UDP廣播的程序,下面就直接介紹實現過程和代碼以及運行的結果。
1、程序實現
UDP廣播程序的實現代碼:
編程
using System;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;using System.Windows.Forms;
namespace UDPBroadcast
{
/// <summary>
/// 在界面上,用戶能夠設置本地進程的IP地址和端口號,並將地址加入某個組播組;
/// 能夠輸入發送消息的目的組的地址,而且勾選「廣播」複選框將採用廣播的方式發送信息
/// 在界面上點擊「接受按鈕」就啓動接收線程,這樣程序就能夠接收廣播或組播的信息
/// </summary>
public partial class UdpBroadcasefrm : Form
{
private UdpClient sendUdpClient;
private UdpClient receiveUdpClient;
// 組播IP地址 IPEndPoint broadcastIpEndPoint;
public UdpBroadcasefrm()
{
InitializeComponent();
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
tbxlocalip.Text = ips[5].ToString();
tbxlocalport.Text = "8002";
// 默認組,組播地址是有範圍
// 具體關於組播和廣播的介紹參照我上一篇博客UDP編程
// 本地組播組
tbxGroupIp.Text = "224.0.0.1";
// 發送到的組播組
tbxSendToGroupIp.Text = "224.0.0.1";
}
ide
// 設置加入組 private void chkbxJoinGtoup_Click(object sender, EventArgs e) { if (chkbxJoinGtoup.Checked == true) { tbxGroupIp.Enabled = false; } else { tbxGroupIp.Enabled = true; tbxGroupIp.Focus(); } } // 選擇發送模式後設置 private void chkbxBroadcast_Click(object sender, EventArgs e) { if (chkbxBroadcast.Checked == true) { tbxSendToGroupIp.Enabled = false; } else { tbxSendToGroupIp.Enabled = true; tbxSendToGroupIp.Focus(); } } // 發送消息 private void btnSend_Click(object sender, EventArgs e) { if (tbxMessageSend.Text == "") { MessageBox.Show("消息內容不能爲空!","提示"); return; } // 根據選擇的模式發送信息 if (chkbxBroadcast.Checked == true) { // 廣播模式(自動得到子網中的IP廣播地址) broadcastIpEndPoint = new IPEndPoint(IPAddress.Broadcast, 8002); } else { // 組播模式 broadcastIpEndPoint = new IPEndPoint(IPAddress.Parse(tbxSendToGroupIp.Text), 8002); } // 啓動發送線程發送消息 Thread sendThread = new Thread(SendMessage); sendThread.Start(tbxMessageSend.Text); } // 發送消息 private void SendMessage(object obj) { string message = obj.ToString(); byte[] messagebytes = Encoding.Unicode.GetBytes(message); sendUdpClient = new UdpClient(); // 發送消息到組播或廣播地址 sendUdpClient.Send(messagebytes, messagebytes.Length, broadcastIpEndPoint); sendUdpClient.Close(); // 清空編輯消息框 ResetMessageText(tbxMessageSend); } // 利用委託回調機制來實現界面上的消息清空操做 delegate void ResetMessageTextCallBack(TextBox textbox); private void ResetMessageText(TextBox textbox) { if (textbox.InvokeRequired) { ResetMessageTextCallBack resetMessageCallback = ResetMessageText; textbox.Invoke(resetMessageCallback, new object[] { textbox }); } else { textbox.Clear(); textbox.Focus(); } } // 接收消息 private void btnReceive_Click(object sender, EventArgs e) { chkbxJoinGtoup.Enabled = false; // 建立接收套接字 IPAddress localIp = IPAddress.Parse(tbxlocalip.Text); IPEndPoint localIpEndPoint = new IPEndPoint(localIp, int.Parse(tbxlocalport.Text)); receiveUdpClient = new UdpClient(localIpEndPoint); // 加入組播組 if (chkbxJoinGtoup.Checked == true) { receiveUdpClient.JoinMulticastGroup(IPAddress.Parse(tbxGroupIp.Text)); receiveUdpClient.Ttl = 50; } // 啓動接受線程 Thread threadReceive = new Thread(ReceiveMessage); threadReceive.Start(); } // 接受消息方法 private void ReceiveMessage() { IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); while (true) { try { // 關閉receiveUdpClient時此時會產生異常 byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIpEndPoint); string receivemessage = Encoding.Unicode.GetString(receiveBytes); // 顯示消息內容 ShowMessage(lstMessageBox, string.Format("{0}[{1}]", remoteIpEndPoint, receivemessage)); } catch { break; } } } // 經過委託回調機制顯示消息內容 delegate void ShowMessageCallBack(ListBox listbox,string text); private void ShowMessage(ListBox listbox, string text) { if (listbox.InvokeRequired) { ShowMessageCallBack showmessageCallback = ShowMessage; listbox.Invoke(showmessageCallback, new object[] { listbox, text }); } else { listbox.Items.Add(text); listbox.SelectedIndex = listbox.Items.Count - 1; listbox.ClearSelected(); } } // 清空消息列表 private void btnClear_Click(object sender, EventArgs e) { lstMessageBox.Items.Clear(); } // 中止接收 private void btnStop_Click(object sender, EventArgs e) { chkbxJoinGtoup.Enabled =true; receiveUdpClient.Close(); } }
}ui
廣播演示結果(接收端直接點接收按鈕後開啓接受線程,在發送端勾選「廣播選項」輸入發送信息點發送按鈕後的界面以下):spa
下面經過把接收端加入組後的結果,首先終止接收線程,而後勾選「加入組」複選框,而後單擊「接收」按鈕從新開啓接收線程,輸出結果以下:
線程
從廣播演示的兩個狀況能夠看出廣播消息會同時向網上的一切進程轉發,不管這個進程是獨立的仍是加入了某個組播組中的進程,均可以接收廣播消息
下面演示下組播的結果:
code
若是把接收端的組地址改成224.0.0.3時,此時發送端發送的消息「組播演示2」將不會發送到不一樣的組播地址,則接收端就接收不到此時的消息。
從組播結果中能夠看出只有加入組播地址224.0.0.2的進程才能接收到信息。
須要注意的地方是:從前面的截圖中能夠看出,不管是廣播仍是組播,僅僅從收到的信息無從知道發送給它的進程的端口號,因此廣播和組播消息都是匿名發送,而且經過對UDP廣播和組播的理解能夠簡單實現一個消息羣發的功能(QQ的羣裏聊天就是這個原理)。
2、 總結
本專題主要是針對上一專題的補充——實現一個簡單的UDP廣播(組播)程序,經過這樣一個發送端能夠發送給在組播地址中的全部用戶和全部子網中的全部用戶。本專題能夠說是對UDP編程的一個擴充吧,但願你們看了本專題後能夠對UDP協議有大體的理解。在下一個專題中會和你們介紹下P2P編程的相關知識。
orm