Unity中可靠的UDP实现
可靠 UDP(Reliable UDP)是一种在用户数据报协议(UDP)基础上,通过添加额外机制来实现可靠数据传输的技术。与传统 UDP 相比,它克服了 UDP 本身不保证数据可靠性、顺序性以及可能丢失数据的缺点,同时保留了 UDP 在某些场景下(如实时性要求高)相对于 TCP 的优势,如低延迟和较少的系统开销。
1. 为什么需要可靠 UDP
实时性应用需求:在一些实时性要求极高的场景,如在线游戏、实时视频流、音频流传输等,TCP 的拥塞控制和重传机制可能会导致较大的延迟,无法满足实时交互的需求。而 UDP 虽然能快速传输数据,但不能保证数据的可靠到达。可靠 UDP 则结合了两者的优点,在保证实时性的同时,尽量确保数据的可靠传输。
特定网络环境适应性:在某些网络环境中,如无线网络、卫星网络等,网络状况可能不稳定,丢包现象较为常见。可靠 UDP 能够通过自身的重传等机制,在这类网络环境下维持相对稳定的数据传输。
2.可靠 UDP 与 TCP 的比较
延迟:
可靠 UDP:由于采用了更灵活的重传机制和较小的头部开销(相较于 TCP),在网络状况良好时,延迟通常比 TCP 低,更适合实时性要求高的应用。
TCP:为了保证数据的可靠传输和顺序性,TCP 在传输过程中需要进行复杂的拥塞控制和流量控制,这可能导致较高的延迟,尤其是在网络拥塞时。
可靠性:
可靠 UDP:通过序列号、重传、去重等机制,在应用层实现了数据的可靠传输,但其可靠性依赖于具体的实现和网络环境。
TCP:在传输层提供了可靠的字节流服务,确保数据无差错、按顺序到达,可靠性更高。
资源消耗:
可靠 UDP:头部开销较小,不需要像 TCP 那样维护复杂的连接状态,因此在系统资源消耗方面相对较低,适合在资源受限的设备上使用。
TCP:需要维护连接状态、进行拥塞控制等,占用较多的系统资源,如内存和 CPU。
3. 应用场景
游戏中的实时操作指令(如玩家移动、技能释放等)对实时性要求极高,同时也需要保证一定的可靠性。可靠 UDP 可以在低延迟的情况下,尽量确保这些指令准确无误地传输到服务器或其他玩家客户端。
5.可靠 UDP 的关键机制实现
序列号管理:
原理:为每个发送的数据包分配一个唯一的序列号。发送方按顺序递增序列号,接收方通过序列号来判断数据包的顺序,从而对乱序到达的数据包进行排序,同时也能识别重复的数据包。
作用:确保接收方接收到的数据顺序与发送方一致,避免因数据包乱序导致的数据处理错误。同时,通过序列号可以实现去重功能,防止重复处理相同的数据。
代码实现:定义一个序列号,在发送方发送消息时递增,将序列号放到网络消息包的头部
// 序列号private int nextSequenceNumber = 0;//序列号放入网络消息包int sequenceNumber = nextSequenceNumber++;byte[] sequenceBytes = BitConverter.GetBytes(sequenceNumber);byte[] combinedData = new byte[sequenceBytes.Length + data.Length];Buffer.BlockCopy(sequenceBytes, 0, combinedData, 0, sequenceBytes.Length);Buffer.BlockCopy(data, 0, combinedData, sequenceBytes.Length, data.Length);
重传机制:
原理:发送方在发送数据包后,启动一个定时器。如果在设定的超时时间内没有收到接收方对该数据包的确认(ACK),则认为数据包丢失,重新发送该数据包。
作用:弥补 UDP 本身不保证数据可靠传输的缺陷,确保即使数据包在网络中丢失,也能最终被接收方正确接收。
代码实现:
// 存储已发送但未确认的数据包private Dictionary<int, Tuple<byte[], Stopwatch>> unacknowledgedPackets = new Dictionary<int, Tuple<byte[], Stopwatch>>();// 存储已接收的数据包序列号,用于去重private HashSet<int> receivedSequenceNumbers = new HashSet<int>();// 当前窗口内已发送的数据包数量private int currentWindowCount = 0;// 基础超时时间(毫秒)private int baseTimeout = 500;// 超时时间调整因子private float timeoutAdjustFactor = 1.5f;// 定时检查未确认的数据包,进行重传public void Update(){List<int> keysToRemove = new List<int>();foreach (var kvp in unacknowledgedPackets){if (kvp.Value.Item2.ElapsedMilliseconds > baseTimeout){// 重传byte[] dataToResend = kvp.Value.Item1;// SendData(dataToResend); // 调整超时时间baseTimeout = (int)(baseTimeout * timeoutAdjustFactor);kvp.Value.Item2.Restart();}}foreach (int key in keysToRemove){unacknowledgedPackets.Remove(key);currentWindowCount--;}}
去重处理:
原理:接收方维护一个已接收序列号的集合。当接收到一个新数据包时,首先检查其序列号是否在该集合中。如果存在,则说明该数据包是重复的,直接丢弃;否则,将序列号加入集合,并处理数据包。
作用:避免接收方对重复的数据进行多次处理,防止数据处理错误和资源浪费。
代码实现:
// 存储已接收的数据包序列号,用于去重private HashSet<int> receivedSequenceNumbers = new HashSet<int>(); int sequenceNumber = BitConverter.ToInt32(data, 0);if (receivedSequenceNumbers.Contains(sequenceNumber)){return null; // 重复数据包,丢弃}receivedSequenceNumbers.Add(sequenceNumber);byte[] actualData = new byte[data.Length - sizeof(int)];Buffer.BlockCopy(data, sizeof(int), actualData, 0, actualData.Length);
滑动窗口机制:
原理:发送方维护一个滑动窗口,窗口内包含可以连续发送的数据包。窗口大小决定了在未收到 ACK 的情况下,发送方可以发送的最大数据包数量。当发送方收到某个已发送数据包的 ACK 时,窗口向前滑动,允许发送新的数据包。
作用:提高数据传输效率,在保证可靠性的前提下,充分利用网络带宽。通过控制窗口大小,还可以在一定程度上避免网络拥塞。
代码实现:
// 滑动窗口大小private int windowSize = 10;// 当前窗口内已发送的数据包数量private int currentWindowCount = 0; // 检查滑动窗口while (currentWindowCount >= windowSize){Thread.Sleep(10); // 等待窗口有空闲位置}currentWindowCount++;
确认机制(ACK):
原理:接收方在正确接收到数据包后,向发送方发送一个确认消息(ACK),其中包含已接收数据包的序列号。发送方根据接收到的 ACK,确认数据包已被成功接收,并从待重传队列中移除相应数据包。
作用:让发送方了解数据包的接收情况,是重传机制和滑动窗口机制正常运行的基础。
代码:
// 发送ACKpublic byte[] GenerateAck(int sequenceNumber){return BitConverter.GetBytes(sequenceNumber);}// 处理接收到的ACKpublic void ProcessAck(byte[] ackData){int sequenceNumber = BitConverter.ToInt32(ackData, 0);if (unacknowledgedPackets.ContainsKey(sequenceNumber)){unacknowledgedPackets.Remove(sequenceNumber);currentWindowCount--;}}
6.测试
测试代码:
结果:
其他有用链接:
Reliable Data Transfer over UDP (youtube.com)
詳解 Reliable UDP (youtube.com)
相关文章:
Unity中可靠的UDP实现
可靠 UDP(Reliable UDP)是一种在用户数据报协议(UDP)基础上,通过添加额外机制来实现可靠数据传输的技术。与传统 UDP 相比,它克服了 UDP 本身不保证数据可靠性、顺序性以及可能丢失数据的缺点,同…...
CentOS 7操作系统部署KVM软件和创建虚拟机
CentOS 7.9操作系统部署KVM软件和配置指南,包括如何创建一个虚拟机。 步骤 1: 检查硬件支持 首先,确认您的CPU支持虚拟化技术,并且已在BIOS中启用: egrep -c (vmx|svm) /proc/cpuinfo 如果输出大于0,则表示支持虚拟…...
Golang GORM系列:GORM分页和排序
高效的数据检索和表示是应用程序开发的关键方面。GORM是健壮的Go对象关系映射库,它为开发人员提供了强大的工具来实现这一点。无论你是在构建动态web应用程序还是数据密集型服务,掌握GORM中的分页和排序使您能够提供无缝且高效的用户体验。本文我们将深入…...
WPF的MVVMLight框架
在NuGet中引入该库: MVVMLight框架中的命令模式的使用: <StackPanel><TextBox Text"{Binding Name}"/><TextBox Text"{Binding Title}"/><Button Content"点我" Command"{Binding ShowCommand…...
微服务SpringCloudAlibaba组件sentinel教程【详解sentinel的使用以及流量控制、熔断降级、热点参数限流等,附有示例+代码】
文章目录 四.Sentinel限流熔断4.1 sentinel介绍4.2 Sentinel 的历史4.3 Sentinel 基本概念资源规则 4.4 Sentinel 功能和设计理念4.4.1 流量控制4.4.2熔断降级什么是熔断降级熔断降级设计理念系统负载保护 4.5 Sentinel 是如何工作的4.6 Sentinel使用4.7 Sentinel 控制台4.8 Sp…...
ScoreFlow:通过基于分数的偏好优化掌握 LLM 智体工作流程
25年2月来自 U of Chicago、Princeton U 和 U of Oxford 的论文“ScoreFlow: Mastering LLM Agent Workflows via Score-based Preference Optimization”。 最近的研究利用大语言模型多智体系统来解决复杂问题,同时试图减少构建它们所需的手动工作量,从…...
数字水印嵌入及提取系统——基于小波变换GUI
数字水印嵌入及提取系统——基于小波变换GUI 基于小波变换的数字水印系统(Matlab代码GUI操作) 【有简洁程序报告】【可作開题完整文档达辩PPT】 本系统主要的内容包括: (1)使用小波变换技术实现二值水印图像的加密、…...
基于海思soc的智能产品开发(图像处理的几种需求)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于一个嵌入式设备来说,如果上面有一个camera,那么就可以有很多的用途。简单的用途就是拍照,比拍照更多一点的…...
【R语言】聚类分析
聚类分析是一种常用的无监督学习方法,是将所观测的事物或者指标进行分类的一种统计分析方法,其目的是通过辨认在某些特征上相似的事物,并将它们分成各种类别。R语言提供了多种聚类分析的方法和包。 方法优点缺点适用场景K-means计算效率高需…...
Spring 项目接入 DeepSeek,分享两种超简单的方式!
⭐自荐一个非常不错的开源 Java 面试指南:JavaGuide (Github 收获148k Star)。这是我在大三开始准备秋招面试的时候创建的,目前已经持续维护 6 年多了,累计提交了 5600 commit ,共有 550 多位贡献者共同参与…...
docker 进阶命令(基于Ubuntu)
数据卷 Volume: 目录映射, 目录挂载 匿名绑定: 匿名绑定的 volume 在容器删除的时候, 数据卷也会被删除, 匿名绑定是不能做到持久化的, 地址一般是 /var/lib/docker/volumes/xxxxx/_data 绑定卷时修改宿主机的目录或文件, 容器内的数据也会同步修改, 反之亦然 # 查看所有 vo…...
机器学习数学基础:29.t检验
t检验学习笔记 一、t检验的定义和用途 t检验是统计学中常用的假设检验方法,主要用于判断样本均值与总体均值间,或两个样本均值间是否存在显著差异。 在实际中应用广泛,例如在医学领域可用于比较两种药物的疗效;在教育领域&…...
HarmonyNext上传用户相册图片到服务器
图片选择就不用说了,直接用 无须申请权限 。 上传图片,步骤和android对比稍微有点复杂,可能是为了安全性考虑,需要将图片先拷贝到缓存目录下面,然后再上传,当然你也可以转成Base64,然后和服务…...
WebAssembly 3.0发布:浏览器端高性能计算迎来新突破!
“WebAssembly 3.0来了,浏览器端的高性能计算将彻底改变!”2025年,WebAssembly(Wasm)迎来了重大更新——WebAssembly 3.0正式发布。这次更新不仅支持多线程和SIMD指令集,还优化了内存管理,让浏览…...
计算机组成原理—— 外围设备(十三)
记住,伟大的成就往往诞生于无数次尝试和失败之后。每一次跌倒,都是为了让你学会如何更加坚定地站立;每一次迷茫,都是为了让你找到内心真正的方向。即使前路漫漫,即使困难重重,心中的火焰也不应熄灭。它代表…...
面试题之Vuex,sessionStorage,localStorage的区别
Vuex、localStorage 和 sessionStorage 都是用于存储数据的技术,但它们在存储范围、存储方式、应用场景等方面存在显著区别。以下是它们的详细对比: 1. 存储范围 Vuex: 是 Vue.js 的状态管理库,用于存储全局状态。 数据存储在内…...
window中git bash使用conda命令
window系统的终端cmd和linux不一样,运行不了.sh文件,为了在window中模仿linux,可以使用gui bash模拟linux的终端。为了在gui bash中使用python环境,由于python环境是在anaconda中创建的,所以需要在gui bash使用conda命…...
象棋掉落动画(局部旋转动画技巧)
1.被撞击阶段:根据被撞击速度,合理设置被撞距离 2.倒地阶段:象棋倒地的同时稍微前移 3.滚地阶段:象棋滚地后停止,在最后5帧内稍微回转一下。这里启用“PRS参数”的旋转来制作局部旋转动画...
Pycharm 2024在解释器提供的python控制台中运行py文件
2024版的界面发生了变化, run with python console搬到了这里:...
课题推荐:高空长航无人机多源信息高精度融合导航技术研究
高空长航无人机多源信息高精度融合导航技术的研究,具有重要的理论意义与应用价值。通过深入研究多源信息融合技术,可以有效提升无人机在高空复杂环境下的导航能力,为无人机的广泛应用提供强有力的技术支持。希望该课题能够得到重视和支持&…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
