C#網(wǎng)絡(luò)編程系列七:UDP編程補(bǔ)充
上次因?yàn)闀r(shí)間的關(guān)系,所以把上一個(gè)專題遺留下的一個(gè)問題在本專題中和大家分享下,本專題主要介紹下如何實(shí)現(xiàn)UDP廣播的程序,下面就直接介紹實(shí)現(xiàn)過程和代碼以及運(yùn)行的結(jié)果。
一、程序?qū)崿F(xiàn)
UDP廣播程序的實(shí)現(xiàn)代碼:
- using System;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Threading;
- using System.Windows.Forms;
- namespace UDPBroadcast
- {
- /// <summary>
- /// 在界面上,用戶可以設(shè)置本地進(jìn)程的IP地址和端口號,并將地址加入某個(gè)組播組;
- /// 可以輸入發(fā)送消息的目的組的地址,并且勾選“廣播”復(fù)選框?qū)⒉捎脧V播的方式發(fā)送信息
- /// 在界面上點(diǎn)擊“接受按鈕”就啟動(dòng)接收線程,這樣程序就可以接收廣播或組播的信息
- /// </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";
- // 默認(rèn)組,組播地址是有范圍
- // 具體關(guān)于組播和廣播的介紹參照我上一篇博客UDP編程
- // 本地組播組
- tbxGroupIp.Text = "224.0.0.1";
- // 發(fā)送到的組播組
- tbxSendToGroupIp.Text = "224.0.0.1";
- }
- // 設(shè)置加入組
- private void chkbxJoinGtoup_Click(object sender, EventArgs e)
- {
- if (chkbxJoinGtoup.Checked == true)
- {
- tbxGroupIp.Enabled = false;
- }
- else
- {
- tbxGroupIp.Enabled = true;
- tbxGroupIp.Focus();
- }
- }
- // 選擇發(fā)送模式后設(shè)置
- private void chkbxBroadcast_Click(object sender, EventArgs e)
- {
- if (chkbxBroadcast.Checked == true)
- {
- tbxSendToGroupIp.Enabled = false;
- }
- else
- {
- tbxSendToGroupIp.Enabled = true;
- tbxSendToGroupIp.Focus();
- }
- }
- // 發(fā)送消息
- private void btnSend_Click(object sender, EventArgs e)
- {
- if (tbxMessageSend.Text == "")
- {
- MessageBox.Show("消息內(nèi)容不能為空!","提示");
- return;
- }
- // 根據(jù)選擇的模式發(fā)送信息
- if (chkbxBroadcast.Checked == true)
- {
- // 廣播模式(自動(dòng)獲得子網(wǎng)中的IP廣播地址)
- broadcastIpEndPoint = new IPEndPoint(IPAddress.Broadcast, 8002);
- }
- else
- {
- // 組播模式
- broadcastIpEndPoint = new IPEndPoint(IPAddress.Parse(tbxSendToGroupIp.Text), 8002);
- }
- // 啟動(dòng)發(fā)送線程發(fā)送消息
- Thread sendThread = new Thread(SendMessage);
- sendThread.Start(tbxMessageSend.Text);
- }
- // 發(fā)送消息
- private void SendMessage(object obj)
- {
- string message = obj.ToString();
- byte[] messagebytes = Encoding.Unicode.GetBytes(message);
- sendUdpClient = new UdpClient();
- // 發(fā)送消息到組播或廣播地址
- sendUdpClient.Send(messagebytes, messagebytes.Length, broadcastIpEndPoint);
- sendUdpClient.Close();
- // 清空編輯消息框
- ResetMessageText(tbxMessageSend);
- }
- // 利用委托回調(diào)機(jī)制來實(shí)現(xiàn)界面上的消息清空操作
- 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;
- // 創(chuàng)建接收套接字
- 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;
- }
- // 啟動(dòng)接受線程
- Thread threadReceive = new Thread(ReceiveMessage);
- threadReceive.Start();
- }
- // 接受消息方法
- private void ReceiveMessage()
- {
- IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
- while (true)
- {
- try
- {
- // 關(guān)閉receiveUdpClient時(shí)此時(shí)會(huì)產(chǎn)生異常
- byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIpEndPoint);
- string receivemessage = Encoding.Unicode.GetString(receiveBytes);
- // 顯示消息內(nèi)容
- ShowMessage(lstMessageBox, string.Format("{0}[{1}]", remoteIpEndPoint, receivemessage));
- }
- catch
- {
- break;
- }
- }
- }
- // 通過委托回調(diào)機(jī)制顯示消息內(nèi)容
- 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();
- }
- }
- }
廣播演示結(jié)果(接收端直接點(diǎn)接收按鈕后開啟接受線程,在發(fā)送端勾選“廣播選項(xiàng)”輸入發(fā)送信息點(diǎn)發(fā)送按鈕后的界面如下):
下面通過把接收端加入組后的結(jié)果,首先終止接收線程,然后勾選“加入組”復(fù)選框,然后單擊“接收”按鈕重新開啟接收線程,輸出結(jié)果如下:
從廣播演示的兩個(gè)情況可以看出廣播消息會(huì)同時(shí)向網(wǎng)上的一切進(jìn)程轉(zhuǎn)發(fā),無論這個(gè)進(jìn)程是獨(dú)立的還是加入了某個(gè)組播組中的進(jìn)程,都可以接收廣播消息
下面演示下組播的結(jié)果:
如果把接收端的組地址改為224.0.0.3時(shí),此時(shí)發(fā)送端發(fā)送的消息“組播演示2”將不會(huì)發(fā)送到不同的組播地址,則接收端就接收不到此時(shí)的消息。
從組播結(jié)果中可以看出只有加入組播地址224.0.0.2的進(jìn)程才能接收到信息。
需要注意的地方是:從前面的截圖中可以看出,不論是廣播還是組播,僅僅從收到的信息無從知道發(fā)送給它的進(jìn)程的端口號,所以廣播和組播消息都是匿名發(fā)送,并且通過對UDP廣播和組播的理解可以簡單實(shí)現(xiàn)一個(gè)消息群發(fā)的功能(QQ的群里聊天就是這個(gè)原理)。
二、 總結(jié)
本專題主要是針對上一專題的補(bǔ)充——實(shí)現(xiàn)一個(gè)簡單的UDP廣播(組播)程序,通過這樣一個(gè)發(fā)送端可以發(fā)送給在組播地址中的所有用戶和所有子網(wǎng)中的所有用戶。本專題可以說是對UDP編程的一個(gè)擴(kuò)充吧,希望大家看了本專題后可以對UDP協(xié)議有大致的理解。在下一個(gè)專題中會(huì)和大家介紹下P2P編程的相關(guān)知識。
全部源碼地址:http://files.cnblogs.com/zhili/UDPBroadcast.zip
原文鏈接:http://www.cnblogs.com/zhili/archive/2012/09/03/UDPBroadcas.html
【編輯推薦】
- C#網(wǎng)絡(luò)編程系列一:網(wǎng)絡(luò)協(xié)議簡介
- C#網(wǎng)絡(luò)編程系列二:HTTP協(xié)議詳解
- C#網(wǎng)絡(luò)編程系列三:自定義Web服務(wù)器
- C#網(wǎng)絡(luò)編程系列四:自定義Web瀏覽器
- C#網(wǎng)絡(luò)編程系列五:TCP編程
- C#網(wǎng)絡(luò)編程系列六:UDP編程
- C#網(wǎng)絡(luò)編程系列八:P2P編程
- C#網(wǎng)絡(luò)編程系列九:類似QQ的即時(shí)通信程序
- C#網(wǎng)絡(luò)編程系列十:實(shí)現(xiàn)簡單的郵件收發(fā)器