UE 可靠UDP实现原理
发送
我们的消息发送都是通过 UChannel 来处理的,通过调用 UChannel::SendBunch 统一处理。 发送的 Bunch 是以 FOutBunch 的形式存在的。当 bReliable 为 True 的时候,表示 Bunch 是可靠的。
发送逻辑直接从UChannel::SendBunch处开始分析
1、大小限制
UE的Bunch大小有限制, 最大Bunch为64K,SendBunch 的时候会去判断当前 Bunch 的大小是否超出限制。

2、Bunch处理(合并小Bunch,拆分大Bunch)
同一个Channel通道,可靠性一样,合并后没有超过单个 Bunch 的限制,可以合并为一个 Bunch。
如果是Actor初始化的包,需要同步CDO信息, 就不能合并。

同理,如果Bunch过大就会拆分,这些被拆分的 Bunch 的 bPartial 字段为1,表示这只是一个包的片段, 收包的时候会根据这个字段进行组包,拆分后的第一个 Bunch 的bPartialInitial 值为1,表示这是拆分后的第一个包, 最后一个包的 bPartialFinal 为 1。


3、可靠Bunch数量限制
如果设置了可靠 Bunch 上限 GCVarNetPartialBunchReliableThreshold,当本次要发送的 OutgoingBunches 的数量和之前 没收到Ack包的数量 超过阈值时,会暂停复制,直到收到了所有可靠消息的 Ack;
当可靠列表溢出的时候,连接会关闭。NumOutRec 为当前可靠的 Bunch 的数量,所以可靠 Bunch 的数量最多256个。

4、可靠 Bunch 预处理
在PrepBunch中对可靠包进行预处理
- OutReliable 保存着每个 Channel 的可靠 Bunch 数量,会去初始化 Bunch 的通道序列号 ChSequence,可以看出每个通道的可靠 Bunch 序列号是递增的。
- 每次发送一个可靠包时 NumOutRec(当前未收到Ack的可靠包数量) 会+1
- 将Bunch加入到 OutRec(发送的未确认的可靠消息数据)中,用于收到Nak后重传。只保存可靠的 Bunch。

5、UChannel::SendRawBunch
将ReceivedAck标记置为0

6、UNetConnection::SendRawBunch
设置 TimeSensitive 为1,先判断SendBuffer(存储BunchHeader和Bunch数据)是否可以装的下这次的Bunch+Header,如果装不下会调用 FlushNet 立即发送出去。然后将Header+Bunch写入SendBuffer中。

7、UNetConnection::Tick
如果有敏感标记TimeSensitive或者超时的时候会直接发送

8、UNetConnection::FlushNet
重置 TimeSensitive ,并且发送Packet。

接收
1、UNetConnection::ReceivedPacket
这一步进行了丢包检测。读取数据包头信息,并根据包头携带的序列号信息和最后一个成功接收到的序列号去判断序列号的增量,正常情况下,所有数据包都会按发出的顺序接收,所有增量会相差1。如果小于1,说明接收到的数据包发生了失序,引擎发送的每一个数据包序列号都是唯一的,不会重用,这种情况下引擎会忽略无效的数据包。


如果大于1,说明发生了丢包,不会立即处理当前的数据,会把当前的数据包加入队列 PacketOrderCache 中,等待收到差值为1的包再一起处理。

2、解析数据包头
然后调用PacketNotify.Update

每个到来的数据包都需要到 PacketNotify 中更新序列号信息。
1、根据包头携带的序列号数据计算出当前确认的序列号数量,然后根据 AckRecord 去更新 InAckSeqAck
2、如果超出数量上限 SequenceHistoryT::Size = 256,则视为收到 Nak
3、从序列号历史记录(History Storage)中判断是 Ack 还是 Nak,然后调用对应的处理函数

3、ReceivedAck
当接收到 Ack 的时候,会对当前确认的包 id 相同的 bunch 修改标志位 ReceivedAck,并且从 OutRec 列表中删除已确认的消息 bunch。

4、ReceivedNak
当我们发送一个可靠的 Bunch 的时候,会把它添加到 OutRec 中,这是一个已发送的未确认的可靠消息列表。当接收到 Nak 的时候,会为每个通道的包 id 为 NakPacketId 的未确认的可靠数据重新发送一次。丢包发生的时候,只会按 Bunch 去重新发送,Bunch 序列号还是原来的 Channel 序列号,而之前的 Packet 是不会重用的,只会生成新的 Packet,以及最新的 PacketId。意味着不会重新发送之前发送的数据包,也不会重用数据包序列号,数据包的发送每一次都是新生成的数据包,数据包序列号都是递增的,不会重复。
1、由于 OutRec 只保存了可靠的数据包,如果是不可靠的消息发生了丢包,引擎是不会重新发送它们的。
2、这里保存的是 RawBunch,如果 Bunch 是拆分的,丢弃了一部分,会导致整个 Bunch 的重新发送。

5、UChannel::ReceivedRawBunch
1、如果是可靠的消息,但是通道序列号不是有序的,则放入接收可靠消息列表 InRec 中,并按通道序列号 ChSequence 顺序存储,同样的,接收的可靠消息列表数量 NumInRec 一样不能超过可靠缓冲区大小256(RELIABLE_BUFFER)。
2、调用 ReceivedNextBunch 接收完之后,会再处理之前缓存的可靠消息列表 InRec,按顺序处理。
6、发送Ack、Nak消息
当收到一份数据的时候,我们会对数据进行确认,会回复 Ack 或者 Nak,写入到序列号历史记录中,由于历史记录最多 256 位,所以当 Ack 累计超过之后,会调用 FlushNet 立即发送。同时改变敏感标志位 TimeSensitive。


相关文章:
UE 可靠UDP实现原理
发送 我们的消息发送都是通过 UChannel 来处理的,通过调用 UChannel::SendBunch 统一处理。 发送的 Bunch 是以 FOutBunch 的形式存在的。当 bReliable 为 True 的时候,表示 Bunch 是可靠的。 发送逻辑直接从UChannel::SendBunch处开始分析 1、大小限…...
智慧博物馆信息化系统建设(1)
博物馆RFID藏品管理系统 博物馆藏品保管是一项十分复杂又繁琐的工作。从事保管工作除了经常、及时地进行藏品的登记、分类、编目、保养和修复等一系列工作外,还需要把有关藏品的信息迅速、正确地提供给利用者。要提高保管工作的效率,达到现代化的科学管理,从发展趋势看,进…...
【数据结构和算法】--- 二叉树(3)--二叉树链式结构的实现(1)
目录 一、二叉树的创建(伪)二、二叉树的遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历 三、二叉树节点个数及高度3.1 二叉树节点个数3.2 二叉树叶子节点个数3.3二叉树第k层节点个数3.4 二叉树查找值为x的节点 四、二叉树的创建(真) 一、二叉树的创建(伪) 在学习二叉树的基本操作前…...
Cesium for Unity包无法加载
太上老君急急如律⚡令⚡ 🥙关闭UnityHub🧀启动梯子🥪cmd 启动UnityHub 🥙关闭UnityHub 🧀启动梯子 🥪cmd 启动UnityHub 把批处理启动文件👈中的exe的路径换成自己的安装目录!保存…...
Leetcode—40.组合总和II【中等】
2023每日刷题(七十七) Leetcode—40.组合总和II 算法思想 实现代码 class Solution { public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<vector<int>> ans;vector<int…...
vscode连不上虚拟机,一直密码错误
最近在做毕设,但是vscode使用连接不上虚拟机,我以为是网络配置的问题,一顿查阅没找到原因。 后来查了一下ssh的日志,发现ssh有消息,但是也提示密码错误。 没找到密码配置格式什么的,经查看sshd配置文件发现…...
力扣每日一题 --- 972. 相等的有理数
本题中的一个难点是怎么判断是否相等,如果自己写判断的话是不是很麻烦,判断整数之后再去判断小数部分,那么我们这题的另一个难点就要登场了,第一个难点让本题的情况变得复杂,第二个难点让本题变得很难想到怎么判断&…...
EXECL 单元格字符串链接 CONCAT :应用:将一行数据转为json
源: 目标 函数表示 CONCAT("data", CHAR(10), "{", CHAR(10), " ", "ulAlarmId : ", A5, CHAR(10), " ", "ulAlarmLevel : ", D5, CHAR(10)," ", "bBo…...
基于Python实现人脸识别相似度对比
目录 引言背景介绍目的和意义 人脸识别的原理人脸图像获取人脸检测与定位人脸特征提取相似度计算 基于Python的人脸相似度对比实现数据集准备人脸图像预处理特征提取相似度计算 引言 背景介绍 人脸识别技术是一种通过计算机对人脸图像进行分析和处理,从而实现自动识…...
CSS 蜡烛效果
<template><view class="holder"><!-- 身子 --><view class="candle"><!-- 光源 --><view class="blinking-glow"></view><!-- 火星子 --><view class="thread"></view>…...
渗透测试之Kali如何利用CVE-2019-0708漏洞渗透Win7
环境: 1.攻击者IP:192.168.1.10 系统: KALI2022(vmware 16.0) 2.靶机IP:192.168.1.8 系统:Windows 7 6.1.7601 Service Pack 1 Build 7601 已开启远程协助RDP服务开启了3389端口 问题描述: KALI 如何利用CVE-2019-0708漏洞渗透Win7 解决方案: 1.打开kali,msf搜索…...
Docker(二)安装指南:主要介绍在 Linux 、Windows 10 和 macOS 上的安装
作者主页: 正函数的个人主页 文章收录专栏: Docker 欢迎大家点赞 👍 收藏 ⭐ 加关注哦! 安装 Docker Docker 分为 stable test 和 nightly 三个更新频道。 官方网站上有各种环境下的 安装指南,这里主要介绍 Docker 在…...
LeetCode 410. 分割数组的最大值
一、题目 1、题目描述 给定一个非负整数数组 nums 和一个整数 k ,你需要将这个数组分成 k 个非空的连续子数组。 设计一个算法使得这 k 个子数组各自和的最大值最小。 2、接口描述 class Solution { public:int splitArray(vector<int>& nums, int …...
linux shell脚本 基础认识
Linux 系统中的 Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当 了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并…...
一文(10图)了解Cornerstone3D核心概念(万字总结附导图)
Cornerstone3D介绍 Cornerstone3D是一个专门为处理三维医学影像而设计的JavaScript库。 它是Cornerstone项目的一部分,旨在为医学影像社区提供高性能、可扩展且易于使用的开源Web工具,专注于提供交互式的3D医学图像浏览体验,适用于多种医学…...
牛客网-----跳石头
题目描述: 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有N块岩石(不含起点和终点的岩石)。在比赛过程中࿰…...
用ChatGPT教学、科研!大学与OpenAI合作
亚利桑那州立大学(简称“ASU”)在官网宣布与OpenAI达成技术合作。从2024年2月份开始,为所有学生提供ChatGPT企业版访问权限,主要用于学习、课程作业和学术研究等。 为了帮助学生更好地学习ChatGPT和大语言模型产品,AS…...
运维平台介绍:视频智能运维平台的视频质量诊断分析和告警中心
目 录 一、视频智能运维平台介绍 (一)平台概述 (二)结构图 (三)功能介绍 1、运维监控 2、视频诊断 3、巡检管理 4、告警管理 5、资产管理 6、工单管理 7、运维…...
GAMES104-现代游戏引擎:从入门到实践 - 物理引擎课程笔记汇总
文章目录 0 入门资料1 物理引擎基本概念Actor & shapesRigid body dynamicsCollision DetectionCollision Resolution 应用与实践Character controllerRagdoll 0 入门资料 GAMES104-现代游戏引擎:从入门到实践_课程视频_bilibiliGAMES104官方账号 - 知乎课程主页…...
【linux】Xorg的工作原理
介绍 在linux系统上执行nvidia-smi时,总有一个进程占用gpu。 1 N/A N/A 2174 G /usr/lib/xorg/Xorg 4MiB /usr/lib/xorg/Xorg 是与X Window System(简称X11或X)相关的一个应用程序。X Window System是一个…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
sshd代码修改banner
sshd服务连接之后会收到字符串: SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢? 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头,…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
