【C# 上位机UDP通讯】
【C# 上位机UDP通讯】
- 1. 概述
- 2. 开发环境
- 3. 功能需求
- 4. 实现步骤
- 4.1 界面设计
- 4.2 UDP监听实现
- 4.3 消息发送功能
- 4.4 线程安全日志显示
- 4.5 资源释放处理
- 5. 使用效果演示
- 6. 关键问题解决方案
- 7. 总结
1. 概述
UDP(用户数据报协议)是一种无连接的传输层协议,具有传输效率高、实时性强的特点,广泛应用于物联网、实时监控、网络广播等场景。本文将详细介绍如何使用 C# 开发一个 UDP 通信上位机软件,实现消息的发送与接收,并实时显示带有时间戳的通信日志。
源码地址:https://download.csdn.net/download/VOR234/90494929
2. 开发环境
- 开发工具:Visual Studio 2022(.NET Framework 4.7.2+)
- 核心类库:
System.Net.Sockets.UdpClient
- 网络调试工具推荐:
- Netassit
- 网络调试助手
- Wireshark
我使用的是Netassit,超级好用!😘😘😘
3. 功能需求
- UDP监听:创建后台线程持续监听指定端口。
- 消息发送:支持向指定IP和端口发送文本消息。
- 实时显示:
- 接收消息时自动显示来源IP和端口。
- 发送消息时记录目标地址。
- 日志记录:所有收发操作均附带毫秒级时间戳。
- 线程安全:跨线程更新UI控件。
4. 实现步骤
4.1 界面设计
核心控件说明:
- 接收日志框:
TextBox
(Multiline + ScrollBars) - 目标IP输入:
TextBox
(默认127.0.0.1) - 目标端口输入:
TextBox
(默认10023) - 消息输入框:
TextBox
- 发送按钮:
Button
完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace UDP_app
{
public partial class Form1 : Form
{
private UdpClient _udpListener;
private Thread _listenThread;
private const int ListenPort = 10023; // 监听端口号
public Form1()
{
InitializeComponent();
InitializeUdpListener();
}
private void InitializeUdpListener()
{
_udpListener = new UdpClient(ListenPort);
_listenThread = new Thread(ReceiveMessages);
_listenThread.IsBackground = true;
_listenThread.Start();
}
private void ReceiveMessages()
{
while (true)
{
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, ListenPort);
byte[] receivedBytes = _udpListener.Receive(ref remoteEndPoint);
string receivedMessage = Encoding.UTF8.GetString(receivedBytes);
AppendTextToOutput($"Received: {receivedMessage} to {remoteEndPoint.Address}:{remoteEndPoint.Port}");
}
}
private void AppendTextToOutput(string text)
{
if (InvokeRequired)
{
Invoke(new Action<string>(AppendTextToOutput), text);
}
else
{
// 添加时间戳
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
text = $"{timestamp} {text}";
txtOutput.AppendText(text + Environment.NewLine);
//显示最后一行
txtOutput.SelectionStart = txtOutput.Text.Length;
txtOutput.ScrollToCaret();
}
}
private void btnSend_Click(object sender, EventArgs e)
{
string targetIp = txtTargetIp.Text;
int targetPort = int.Parse(txtTargetPort.Text);
string message = txtMessage.Text;
using (UdpClient udpClient = new UdpClient())
{
var sendBytes = Encoding.UTF8.GetBytes(message);
udpClient.Send(sendBytes, sendBytes.Length, targetIp, targetPort);
AppendTextToOutput($"Sent: {message} to {targetIp}:{targetPort}");
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
_udpListener.Close();
}
}
}
4.2 UDP监听实现
通过后台线程持续监听UDP端口:
private UdpClient _udpListener;
private Thread _listenThread;
private const int ListenPort = 10023;
private void InitializeUdpListener()
{
_udpListener = new UdpClient(ListenPort);
_listenThread = new Thread(ReceiveMessages);
_listenThread.IsBackground = true; // 设置为后台线程
_listenThread.Start();
}
private void ReceiveMessages()
{
while (true)
{
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, ListenPort);
byte[] receivedBytes = _udpListener.Receive(ref remoteEndPoint);
string receivedMessage = Encoding.UTF8.GetString(receivedBytes);
AppendTextToOutput($"Received: {receivedMessage} from {remoteEndPoint}");
}
}
4.3 消息发送功能
使用独立的UdpClient
实例发送数据:
private void btnSend_Click(object sender, EventArgs e)
{
string targetIp = txtTargetIp.Text;
int targetPort = int.Parse(txtTargetPort.Text);
string message = txtMessage.Text;
using (UdpClient udpClient = new UdpClient())
{
byte[] sendBytes = Encoding.UTF8.GetBytes(message);
udpClient.Send(sendBytes, sendBytes.Length, targetIp, targetPort);
AppendTextToOutput($"Sent: {message} to {targetIp}:{targetPort}");
}
}
4.4 线程安全日志显示
使用Invoke
跨线程更新UI:
private void AppendTextToOutput(string text)
{
if (InvokeRequired)
{
Invoke(new Action<string>(AppendTextToOutput), text);
}
else
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
txtOutput.AppendText($"[{timestamp}] {text}\r\n");
txtOutput.ScrollToCaret(); // 自动滚动到底部
}
}
4.5 资源释放处理
窗口关闭时释放UDP资源:
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
_udpListener?.Close(); // 释放监听器
_listenThread?.Join(500); // 等待线程退出
}
5. 使用效果演示
- 启动监听:运行程序后自动开始监听10023端口
- 发送测试:
- 目标地址填写本机IP(127.0.0.1)
- 输入消息内容点击发送
- 环回测试:发送的消息会立即被本机接收
6. 关键问题解决方案
- 数据粘包问题:UDP本身不保证数据完整性,建议:
- 添加消息头尾标识
- 实现应用层协议封装
- 大文件传输:需分片发送并重组,示例分片方法:
// 文件分片发送(示例)
byte[] fileData = File.ReadAllBytes("test.jpg");
int chunkSize = 1024;
for (int i = 0; i < fileData.Length; i += chunkSize)
{
int size = Math.Min(chunkSize, fileData.Length - i);
byte[] chunk = new byte[size + 4];
Buffer.BlockCopy(BitConverter.GetBytes(i), 0, chunk, 0, 4);
Buffer.BlockCopy(fileData, i, chunk, 4, size);
udpClient.Send(chunk, chunk.Length, targetIp, targetPort);
}
7. 总结
本文实现了一个基础的UDP通信上位机程序,具有以下特点:
- 支持双向通信(发送/接收)
- 实时显示带时间戳的通信日志
- 自动处理跨线程UI更新
- 完善的资源释放机制
扩展方向:
- 增加十六进制收发功能
- 实现消息过滤机制
- 添加数据统计功能(收发计数器)
- 支持多网卡绑定选择
完整源码下载:【C# UDP通信上位机源码】
推荐工具:
- 网络抓包分析工具:Wireshark
- 高性能UDP测试工具:iperf
参考文献:
- MSDN UdpClient文档
- RFC 768 - UDP协议规范