目录
UDP是user datagram protocol的简称,中文名是用户数据报协议,它是网络信息传输的另一种形式。UDP通信和TCP通信不同,基于UDP的信息传递更快,但不提供可靠的保证。使用UDP传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。
虽然UDP是一种不可靠的协议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用UDP。基于UDP通信的基本模式如下:
- 将数据打包(称为数据包),然后将数据包发往目的地。
- 接收别人发来的数据包,然后查看数据包。
在C#中,UdpClient类用于在阻止同步模式下发送和接收无连接 UDP数据报。因为UDP是无连传输协议,所以不需要在发送和接收数据前建立远程主机连接,但可以选择使用下面两种方法之一建立默认远程主机。
- 使用远程主机名和端口号作为参数创建UdpClient类的实例。
- 创建UdpClient类的实例,然后调用Connect方法。
一、UdpClient类
UdpClient类的常用属性、方法及说明如表:
|----------------------|------------------------|
| 属性及方法 | 说明 |
| Available属性 | 获取从网络接收的可读取的数据量 |
| Client属性 | 获取或设置基础网络Socket |
| BeginReceive方法 | 从远程主机异步接收数据报 |
| BeginSend方法 | 将数据报异步发送到远程主机 |
| Close方法 | 关闭UDP连接 |
| Connect方法 | 建立默认远程主机 |
| EndReceive方法 | 结束挂起的异步接收 |
| EndSend方法 | 结束挂起的异步发送 |
| Receive方法 | 返回已由远程主机发送的UDP数据报 |
| Send方法 | 将UDP数据报发送到远程主机 |
| EnableBroadcast属性 | 是否接收或发送广播 |
| Active属性 | 获取或者设置一个值指示是否已建立默认远程主机 |
| JoinMulticastGroup方法 | 将UdpClient添加到多路广播组 |
| DropMulticastGroup方法 | 将UdpClient退出多路广播组 |
二、示例
本实例要求主机不断地重复播出节目预报,这样可以保证加入到同一组的主机随时接收到广播信 。接收者将正在接收的信息放在一个文本框中,并将接收的全部信息放在另一个文本框中。
1.源码
(1)Client
cs
// Client
// 创建接收广播项目Clent(Windows窗体应用程序),
// 单击"开始接收"按钮,系统开始接收主机播出的信息;
// 单击"停止接收"按钮,系统会停止接收广播主机播出的信息。
using System.Net.Sockets;
using System.Net;
using System.Text;
namespace Client
{
public partial class Form1 : Form
{
private Button? button1;
private Button? button2;
private TextBox? textBox1;
private TextBox? textBox2;
public Form1()
{
InitializeComponent();
Load += new EventHandler(Form1_Load);
CheckForIllegalCrossThreadCalls = false; //在其他线程中可以调用主窗体控件
}
private CancellationTokenSource? cancellationToken1;
private bool flag = true; //定义一个bool变量,标识是否接收数据
private UdpClient? udp; //创建UdpClient对象
private Thread? thread; //创建线程对象
private void Form1_Load(object? sender, EventArgs e)
{
//
// button1
//
button1 = new Button
{
BackColor = Color.Red,
FlatStyle = FlatStyle.Flat,
Font = new Font("宋体", 10F, FontStyle.Bold, GraphicsUnit.Point, 134),
Location = new Point(228, 5),
Name = "button1",
Size = new Size(85, 32),
TabIndex = 0,
Text = "开始接收",
UseVisualStyleBackColor = false
};
button1.FlatAppearance.BorderSize = 0;
button1.Click += new EventHandler(Button1_Click);
//
// button2
//
button2 = new Button
{
BackColor = Color.Yellow,
FlatStyle = FlatStyle.Flat,
Font = new Font("宋体", 10F, FontStyle.Bold, GraphicsUnit.Point, 134),
Location = new Point(319, 5),
Name = "button2",
Size = new Size(85, 32),
TabIndex = 1,
Text = "停止接收",
UseVisualStyleBackColor = false
};
button2.FlatAppearance.BorderSize = 0;
button2.Click += new EventHandler(Button2_Click);
//
// textBox1
//
textBox1 = new TextBox
{
Location = new Point(7, 54),
Multiline = true,
Name = "textBox1",
ScrollBars = ScrollBars.Both,
Size = new Size(311, 133),
TabIndex = 2
};
//
// textBox2
//
textBox2 = new TextBox
{
ForeColor = Color.Blue,
Location = new Point(319, 54),
Multiline = true,
Name = "textBox2",
ScrollBars = ScrollBars.Both,
Size = new Size(306, 133),
TabIndex = 3
};
//
// Form1
//
AutoScaleDimensions = new SizeF(6F, 12F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(638, 193);
Controls.Add(textBox2);
Controls.Add(textBox1);
Controls.Add(button2);
Controls.Add(button1);
Name = "Form1";
StartPosition = FormStartPosition.CenterScreen;
Text = "Client";
}
private void Button1_Click(object? sender, EventArgs e)
{
udp = new UdpClient(888);
flag = true;
IPEndPoint ipendpoint = new(IPAddress.Any, 888); //创建IPEndPoint对象,用来显示响应主机的标识
thread = new Thread(() => //新开线程,执行接收数据操作
{
while (flag)
{
try
{
if (udp.Available <= 0) continue; //判断是否有网络数据
if (udp.Client == null) return; //判断连接是否为空
byte[] bytes = udp.Receive(ref ipendpoint); //调用UdpClient对象的Receive方法获得从远程主机返回的UDP数据报
string str = Encoding.Default.GetString(bytes);//将获得的UDP数据报转换为字符串形式
textBox1!.Text = "正在接收的信息:\n" + str; //显示正在接收的数据
textBox2!.Text += "\n" + str; //显示接收的所有数据
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);//错误提示
}
Thread.Sleep(1000); //线程休眠1秒
}
});
thread.Start(); //启动线程
}
private void Button2_Click(object? sender, EventArgs e)
{
cancellationToken1 = new CancellationTokenSource();
flag = false; //不接收数据
if (thread!.ThreadState == ThreadState.Running) //判断线程是否运行
cancellationToken1.Cancel(); //关闭线程
udp!.Close(); //关闭连接
}
}
}
(2)Server
cs
// Server,先开Server后开Client
// 广播数据报程序
// 创建广播主机项目Server(控制台应用程序),在Main()方法中创建UDP连接;
// 然后通过UDP 不断向外发送广播信息。
using System.Text;
using System.Net.Sockets;
namespace Server
{
class Program
{
static readonly UdpClient udp = new();// 创建UdpClient对象
static void Main(string[] args)
{
udp.Connect("127.0.0.1", 888); //调用UdpClient对象的Connect方法建立默认远程主机
while (true)
{
Thread thread = new(() =>
{
try
{
string str = "(" + DateTime.Now.ToLongTimeString();
str += ")节目预报:八点有大型晚会,请收听";
byte[] sendBytes = Encoding.Default.GetBytes(str); //定义一个字节数组,用来存放发送到远程主机的信息
Console.WriteLine(str);
udp.Send(sendBytes, sendBytes.Length); //调用UdpClient对象的Send方法将UDP数据报发送到远程主机
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
});
thread.Start(); //启动线程
Thread.Sleep(1000);//线程休眠1秒
}
}
}
}