【C# 上位机UDP通讯】

【C# 上位机UDP通讯】

    • [1. 概述](#1. 概述)
    • [2. 开发环境](#2. 开发环境)
    • [3. 功能需求](#3. 功能需求)
    • [4. 实现步骤](#4. 实现步骤)
      • [4.1 界面设计](#4.1 界面设计)
      • [4.2 UDP监听实现](#4.2 UDP监听实现)
      • [4.3 消息发送功能](#4.3 消息发送功能)
      • [4.4 线程安全日志显示](#4.4 线程安全日志显示)
      • [4.5 资源释放处理](#4.5 资源释放处理)
    • [5. 使用效果演示](#5. 使用效果演示)
    • [6. 关键问题解决方案](#6. 关键问题解决方案)
    • [7. 总结](#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
  • 网络调试工具推荐

3. 功能需求

  1. UDP监听:创建后台线程持续监听指定端口。
  2. 消息发送:支持向指定IP和端口发送文本消息。
  3. 实时显示
    • 接收消息时自动显示来源IP和端口。
    • 发送消息时记录目标地址。
  4. 日志记录:所有收发操作均附带毫秒级时间戳。
  5. 线程安全:跨线程更新UI控件。

4. 实现步骤

4.1 界面设计

核心控件说明:

  • 接收日志框:TextBox(Multiline + ScrollBars)
  • 目标IP输入:TextBox(默认127.0.0.1)
  • 目标端口输入:TextBox(默认10023)
  • 消息输入框:TextBox
  • 发送按钮:Button
    完整代码
csharp 复制代码
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端口:

csharp 复制代码
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实例发送数据:

csharp 复制代码
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:

csharp 复制代码
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资源:

csharp 复制代码
protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);
    _udpListener?.Close(); // 释放监听器
    _listenThread?.Join(500); // 等待线程退出
}

5. 使用效果演示

  1. 启动监听:运行程序后自动开始监听10023端口
  2. 发送测试
    • 目标地址填写本机IP(127.0.0.1)
    • 输入消息内容点击发送
  3. 环回测试:发送的消息会立即被本机接收

6. 关键问题解决方案

  1. 数据粘包问题 :UDP本身不保证数据完整性,建议:
    • 添加消息头尾标识
    • 实现应用层协议封装
  2. 大文件传输:需分片发送并重组,示例分片方法:
csharp 复制代码
// 文件分片发送(示例)
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更新
  • 完善的资源释放机制

扩展方向

  1. 增加十六进制收发功能
  2. 实现消息过滤机制
  3. 添加数据统计功能(收发计数器)
  4. 支持多网卡绑定选择

完整源码下载:【C# UDP通信上位机源码】


推荐工具

参考文献

相关推荐
aramae9 分钟前
模拟实现strcmp()(C语言)
c语言·开发语言·后端
泡海椒1 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
Beyond_System|系统之外2 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
景熙55232 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
c#上位机3 小时前
C#上位机项目实战——Task.Run执行带参数的方法
c#·上位机
Bruce_Liuxiaowei5 小时前
Python 实例赋值遮蔽类属性:一个从不报错的静默陷阱
开发语言·python·语法糖
aramae6 小时前
MySQL内置函数(7)
开发语言·笔记·后端·mysql·其他
Lost of 程序猿9 小时前
用 YARP 为 .NET 微服务搭一座“立交桥“:路由转发与生产配置实践
c#·asp.net
码行山野赴时序归途9 小时前
链表家族收官篇:循环链表
c语言·开发语言·数据结构·链表
景熙55239 小时前
单体项目编写思路和落地形式
java·开发语言