转自:http://www.cnblogs.com/zhili/archive/2012/09/03/2666974.html

上次因为时间的关系,所以把上一个专题遗留下的一个问题在本专题中和大家分享下,本专题主要介绍下如何实现UDP广播的程序,下面就直接介绍实现过程和代码以及运行的结果。

一、程序实现

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";
} // 设置加入组
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();
} }
}

广播演示结果(接收端直接点接收按钮后开启接受线程,在发送端勾选“广播选项”输入发送信息点发送按钮后的界面如下):

下面通过把接收端加入组后的结果,首先终止接收线程,然后勾选“加入组”复选框,然后单击“接收”按钮重新开启接收线程,输出结果如下:

从广播演示的两个情况可以看出广播消息会同时向网上的一切进程转发,无论这个进程是独立的还是加入了某个组播组中的进程,都可以接收广播消息

下面演示下组播的结果:

如果把接收端的组地址改为224.0.0.3时,此时发送端发送的消息“组播演示2”将不会发送到不同的组播地址,则接收端就接收不到此时的消息。

从组播结果中可以看出只有加入组播地址224.0.0.2的进程才能接收到信息。

需要注意的地方是:从前面的截图中可以看出,不论是广播还是组播,仅仅从收到的信息无从知道发送给它的进程的端口号,所以广播和组播消息都是匿名发送,并且通过对UDP广播和组播的理解可以简单实现一个消息群发的功能(QQ的群里聊天就是这个原理)。

二、 总结

本专题主要是针对上一专题的补充——实现一个简单的UDP广播(组播)程序,通过这样一个发送端可以发送给在组播地址中的所有用户和所有子网中的所有用户。本专题可以说是对UDP编程的一个扩充吧,希望大家看了本专题后可以对UDP协议有大致的理解。在下一个专题中会和大家介绍下P2P编程的相关知识。

全部源码地址:http://files.cnblogs.com/zhili/UDPBroadcast.zip

[C# 网络编程系列]专题七:UDP编程补充——UDP广播程序的实现的更多相关文章

  1. [C# 网络编程系列]专题六:UDP编程

    转自:http://www.cnblogs.com/zhili/archive/2012/09/01/2659167.html 引用: 前一个专题简单介绍了TCP编程的一些知识,UDP与TCP地位相当 ...

  2. [C# 网络编程系列]专题九:实现类似QQ的即时通信程序

    转自:http://www.cnblogs.com/zhili/archive/2012/09/23/2666987.html 引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例 ...

  3. [C# 网络编程系列]专题八:P2P编程

    引言: 前面的介绍专题中有朋友向我留言说介绍下关于P2P相关的内容的,首先本人对于C#网络编程也不是什么大牛,因为能力的关系,也只能把自己的一些学习过程和自己的一些学习过程中的理解和大家分享下的,下面 ...

  4. [C# 网络编程系列]专题四:自定义Web浏览器

    转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...

  5. [C# 网络编程系列]专题五:TCP编程

    转自:http://www.cnblogs.com/zhili/archive/2012/08/25/2656840.html 前言 前面专题的例子都是基于应用层上的HTTP协议的介绍, 现在本专题来 ...

  6. 详解C# 网络编程系列:实现类似QQ的即时通信程序

    https://www.jb51.net/article/101289.htm 引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net ...

  7. [C#网络编程系列]专题一:网络协议简介

    转自:http://www.cnblogs.com/zhili/archive/2012/08/11/NetWorkProgramming.html 因为这段时间都在研究C#网络编程的一些知识, 所以 ...

  8. [C# 网络编程系列]专题三:自定义Web服务器

    转自:http://www.cnblogs.com/zhili/archive/2012/08/23/2652460.html 前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网 ...

  9. [C# 网络编程系列]专题十:实现简单的邮件收发器

    转自:http://www.cnblogs.com/zhili/archive/2012/09/24/2689892.html 引言: 在我们的平常工作中,邮件的发送和接收应该是我们经常要使用到的功能 ...

随机推荐

  1. JavaScript高级程序设计(一):JavaScript简介

    一.JavaScript实现 1.一个完整的JavaScript包含三个部分组成: 1)ECMAScript 核心 2)DOM文档对象模型 3)BOM浏览器对象模型 2.文档对象模型(DOM) 文档对 ...

  2. spring boot 配置文件提示自定义配置属性

    1.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  3. C语言-求1-20的阶乘的和(函数的递归)

    // //  main.c //  C语言 // //  Created by wanghy on 15/9/5. //  Copyright (c) 2015年 wanghy. All rights ...

  4. 安装会声会影x8后打不开的解决方法

    操作系统:Windows 7 症状:双击程序图标后一直停留在购买介绍页,主程序界面一直无法打开 解决方法:删除系统补丁KB3126587和KB3126593

  5. c++ fstream中seekg()和seekp()的用法

    转自:http://blog.sina.com.cn/s/blog_679f85d40100mysi.html 先说一下C语言中fseek()的功能: 函数原型:int fseek(FILE *fp, ...

  6. Struts2配置文件_常量属性_独立测试分析

    <constant name="struts.devMode" value="true" /> 设置开发模式,可以了解详细信息,该属性指定视图标签默 ...

  7. tp_shop解读1

    由于想弄一个商城,因此研究了一下tp_shop,这个据说能完成几乎所有的功能. 考虑到原有的例子过于复杂,因此把所有相关的数据都删除了,结果上来就出错了,查了两天,大致弄清楚了状况. 关于错误的原因 ...

  8. 网络安全设备Bypass功能介绍及分析

    from:http://netsecurity.51cto.com/art/200910/159948.htm 网络安全平台厂商往往需要用到一项比较特殊的技术,那就是Bypass,那么到底什么是Byp ...

  9. 《APUE》第三章笔记(1)

    以下内容是我看<APUE>第二版第三章的笔记,有错还希望指出来,谢谢. unbuffered I/O,跟buffered I/O相对,buffered I/O就是 ISO C标准下的标准输 ...

  10. PHP curl 采集内容之规则 1

    <?phpheader("Content-type:text/html; charset=utf-8");$pattern = '/xxx(.*)yyyy/isU'; //i ...