【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通信上位机源码】


推荐工具

参考文献

相关推荐
江沉晚呤时4 分钟前
深入解析 .NET 中的依赖项加载机制:原理、实现与最佳实践
前端·数据库·c#·.netcore
倔强的石头1068 分钟前
【C++指南】string(三):basic_string底层原理与模拟实现详解
开发语言·c++·算法
程序猿多布1 小时前
C# 语法糖
c#
机器鱼2 小时前
1-1 MATLAB深度极限学习机
开发语言·matlab
苏墨瀚2 小时前
C#语言的响应式设计
开发语言·后端·golang
共享家95273 小时前
链表操作:分区与回文判断
c语言·开发语言·数据结构·leetcode·链表
江沉晚呤时3 小时前
C#原型模式:通过克隆对象来优化创建过程
java·开发语言·microsoft·c#·asp.net·.netcore
苏墨瀚4 小时前
SQL语言的散点图
开发语言·后端·golang
Suwg2096 小时前
【Java导出word】使用poi-tl轻松实现Java导出数据到Word文档
java·开发语言·word·poi-tl
水w6 小时前
【pyCharm Git】根据dev分支新建dev_y分支,本地也新建dev_y分支,并将代码提交到Gitlab上的新分支dev_y上。
开发语言·git·python·pycharm·pull·push·branch