Unity 基于UDP实现本地时间与网络时间校验 防客户端修改日期作弊
新建一个Unity GameObject 挂上NTPComponent脚本

时间校验

源码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.Networking;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.Linq;namespace GameContent
{/// <summary>/// 启动游戏后,将所有地址列表遍历/// </summary>[DisallowMultipleComponent]public class NTPComponent : MonoBehaviour{[Range( 5f, 60f )]public float CheckDuration = 5f;[Header( "NTP服务器域名列表" )]public List<string> NTPServerAddressList = new List<string>{"cn.pool.ntp.org",//国际NTP快速授时服务"ntp.ntsc.ac.cn","pool.ntp.org" ,//全球通用"time1.google.com" ,//谷歌"time2.google.com","time3.google.com","time4.google.com","time.apple.com" ,//苹果"time1.apple.com","time2.apple.com","time3.apple.com","time.windows.com" ,//微软"time.nist.gov" ,//美国"cn.ntp.org.cn",//中国"stdtime.gov.hk",//香港"ntp.tencent.com",//腾讯云"ntp.aliyun.com",//阿里云};/// <summary>/// 网络时间是否生效中/// </summary>public bool IsValid { get; private set; }/// <summary>/// 当前Utc时间/// </summary>public DateTime NowUtc { get; private set; }[ReadOnly] public bool IsSyncState = false;//[SerializeField]private float mResidualCheckTime = 0f;private Socket mSocket = null;private void Start( ){mResidualCheckTime = CheckDuration;IsValid = false;NowUtc = DateTime.UtcNow;SearchNTPAddresses( );}#region NTP服务private void Update( ){if ( IsValid )NowUtc.AddSeconds( Time.unscaledDeltaTime );//没间隔n秒就同步一次utc时间mResidualCheckTime -= Time.unscaledDeltaTime;if ( mResidualCheckTime <= 0 ){mResidualCheckTime = CheckDuration;SearchNTPAddresses( );}}public async void SearchNTPAddresses( ){var tasks = NTPServerAddressList.Select( serverAddress => Task.Run( async ( ) => await GetNetworkUtcTimeAsync( serverAddress, 2000 ) ) ).ToArray( );while ( tasks.Length > 0 ){var completedTask = await Task.WhenAny( tasks );DateTime networkDateTime = completedTask.Result;if ( networkDateTime != DateTime.MinValue ){bool oldState = IsValid;IsValid = true;NowUtc = completedTask.Result;//Debug.Log( $"<Color=#FF0000>NTP = {NowUtc}</Color>" );TimeSpan diff = NowUtc - DateTime.UtcNow;IsSyncState = Mathf.Abs( ( float ) diff.TotalSeconds ) <= 10;if ( oldState == false )Fire.Event( GameEvent.ConnectNTPEvent, this );return;}else{tasks = tasks.Where( task => task != completedTask ).ToArray( );}}IsValid = false;//GameEntry.Event.Fire(this, ConnectNTPEventArgs.Create(false));}/// <summary>/// 异步获取时间 utc时间/// </summary>private async Task<DateTime> GetNetworkUtcTimeAsync( string ntpServer, int timeoutMilliseconds = 5000 ){try{const int udpPort = 123;var ntpData = new byte[ 48 ];ntpData[ 0 ] = 0x1B;var addresses = await Dns.GetHostAddressesAsync( ntpServer );var ipEndPoint = new IPEndPoint( addresses[ 0 ], udpPort );var socket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );// 设置超时时间socket.ReceiveTimeout = timeoutMilliseconds;await socket.ConnectAsync( ipEndPoint );await socket.SendAsync( new ArraySegment<byte>( ntpData ), SocketFlags.None );var receiveBuffer = new byte[ 48 ];await socket.ReceiveAsync( new ArraySegment<byte>( receiveBuffer ), SocketFlags.None );socket.Dispose( );const byte serverReplyTime = 40;ulong intPart = BitConverter.ToUInt32( receiveBuffer, serverReplyTime );ulong fractPart = BitConverter.ToUInt32( receiveBuffer, serverReplyTime + 4 );intPart = SwapEndianness( intPart );fractPart = SwapEndianness( fractPart );var milliseconds = ( intPart * 1000 ) + ( ( fractPart * 1000 ) / 0x100000000L );var networkUtcDateTime = new DateTime( 1900, 1, 1 ).AddMilliseconds( ( long ) milliseconds );//TimeZoneInfo serverTimeZone = TimeZoneInfo.Local; // 服务器的时区//var networkDateTime = TimeZoneInfo.ConvertTimeFromUtc(networkUtcDateTime, serverTimeZone);return networkUtcDateTime;}catch ( Exception ex ){// 出现异常,返回 null 或抛出错误,视情况而定//Debug.Log("获取网络时间失败: " + ex.Message);return DateTime.MinValue;}}// 交换字节顺序,将大端序转换为小端序或反之private uint SwapEndianness( ulong x ){return ( uint ) ( ( ( x & 0x000000ff ) << 24 ) +( ( x & 0x0000ff00 ) << 8 ) +( ( x & 0x00ff0000 ) >> 8 ) +( ( x & 0xff000000 ) >> 24 ) );}#endregion}
}相关文章:
Unity 基于UDP实现本地时间与网络时间校验 防客户端修改日期作弊
新建一个Unity GameObject 挂上NTPComponent脚本 时间校验 源码 using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using UnityEngine.Networking; using System.Text; using System.Net.Sockets; using System.Net; using Sys…...
ArduPilot开源代码之MatekSys Optical Flow 3901-L0X
ArduPilot开源代码之MatekSys Optical Flow 3901-L0X 1. 源由2. 安装3. 参数配置3.1 配置光流定位3.2 配置激光测距3.3 辅助配置 4. 测试4.1 光流数据测试4.2 测距数据测试4.3 飞行注意事项4.4 实际飞行测试 5. 参考资料 1. 源由 之前介绍过MatekSys Optical Flow 3901-L0X模块…...
【时钟】分布式时钟HLC|Logical Time|Vector Clock|True Time
目录 简略 详细 附录 1 分布式系统不能使用NTP的原因 简略 分布式系统中不同于单机系统不能使用NTP(网络时间协议(Network Time Protocol))来获取时间,所以我们需要一个特别的方式来获取分布式系统中的时间,mvcc也是使用time保证读…...
人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新
随着科技的飞速发展,人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新。富唯智能移动机器人,以其独特的3D视觉技术,赋予了移动机器人一双“智慧之眼”,从而为现代工业自动化带来了前所未有的突破。 富唯智能移动机器…...
NSSCTF 简单包含
开启环境: 使用POST传flag,flag目录/var/www/html/flag.php 先使用post来尝试读取该flag.php 没反应: 查看一下源码index.php,看有什么条件 base64解密: <?php$path $_POST["flag"];if (strlen(file_get_contents(php://input)) <…...
FlinkSQL处理Canal-JSON数据
背景信息 Canal是一个CDC(ChangeLog Data Capture,变更日志数据捕获)工具,可以实时地将MySQL变更传输到其他系统。Canal为变更日志提供了统一的数据格式,并支持使用JSON或protobuf序列化消息(Canal默认使用…...
玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— DevEco Studio下载与安装
一、下载DevEco Studio IDE开发工具 1. 登录鸿蒙官网 网址为: 华为HarmonyOS智能终端操作系统官网 | 应用设备分布式开发者生态 页面如下: 2. 搜索“DevEco Studio IDE” 点击右上角的“请输入关键词”,在其中搜索“DevEc…...
大模型上下文长度的超强扩展:从LongLora到LongQLora
前言 本文一开始是《七月论文审稿GPT第2版:从Meta Nougat、GPT4审稿到Mistral、LongLora Llama》中4.3节的内容,但考虑到 一方面,LongLora的实用性较高二方面,为了把LongLora和LongQLora更好的写清楚,而不至于受篇幅…...
pdf格式转换为txt格式
pdf文档转换为txt文档 首先在python3虚拟环境中安装PyPDF2 Python 3.6.8 (default, Jun 20 2023, 11:53:23) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux Type "help", "copyright", "credits" or "license" for more infor…...
scss使用for循环遍历,动态赋值类名并配置不同颜色
需求:后端要传入不同的等级,前端通过等级展示不同的字体颜色,通过scss遍历更有利于动态修改颜色或者增删等级 1.通过 for $i from 1 through 4 定义循环,索引值为i 2.nth($colors, $i) 取出对应的颜色 $colors: #ff0000, #00ff…...
GaussDB数据库使用COPY命令导数
目录 一、前言 二、GaussDB数据库使用COPY命令导数语法 1、语法COPY FROM 2、语法COPY TO 3、特别说明及参数示意 三、GaussDB数据库使用COPY命令导数示例 1、操作步骤 2、准备工作(示例) 3、把一个表的数据拷贝到一个文件(示例&…...
SunFMEA软件免费试用:FMEA的目标和限制是什么?
免费试用FMEA软件-免费版-SunFMEA FMEA,即故障模式与影响分析,是一种预防性的质量工具,旨在识别、评估和优先处理潜在的故障模式及其对系统性能的影响。其目标是提高产品和过程的可靠性和安全性,降低产品故障的风险,并…...
【Redis交响乐】Redis中的数据类型/内部编码/单线程模型
文章目录 一. Redis中的数据类型和内部编码二. Redis的单线程模型面试题: redis是单线程模型,为什么效率之高,速度之快呢? 在上一篇博客中我们讲述了Redis中的通用命令,本篇博客中我们将围绕每个数据结构来介绍相关命令. 一. Redis中的数据类型和内部编码 type命令实际返回的…...
APK 瘦身
APK 瘦身的主要原因是考虑应用的下载转化率和留存率,应用太大了,用户可能就不下载了。再者,因为手机空间问题,用户有可能会卸载一些占用空间比较大的应用,所以,应用的大小也会影响留存率。 1 APK 的结构 …...
GitHub上的15000个Go模块存储库易受劫持攻击
内容概要: 目前研究发现,GitHub上超过15000个Go模块存储库容易受到一种名为“重新劫持”的攻击。 由于GitHub用户名的更改会造成9000多个存储库容易被重新劫持,同时因为帐户删除,会对6000多个存储库造成重新劫持的危机。目前统计…...
避免3ds Max效果图渲染一片黑的4个正确解决方法
在进行3ds Max效果图渲染时,有时候会遇到渲染一片黑的情况,这给我们的工作带来了很大的困扰。为了解决这个问题,下面我将介绍4个正确的解决方法。 1.相机位置 首先需要考虑场景内的相机位置是否有问题。如果相机放在了模型的内部或者墙体的外…...
UI演示双视图立体匹配与重建
相关文章: PyQt5和Qt designer的详细安装教程:https://blog.csdn.net/qq_43811536/article/details/135185233?spm1001.2014.3001.5501Qt designer界面和所有组件功能的详细介绍:https://blog.csdn.net/qq_43811536/article/details/1351868…...
添加一个编辑的小功能(PHP的Laravel)
一个编辑的按钮可以弹出会话框修改断更天数 前台 加一个编辑按钮的样式,他的名字是固定好的 之前有人封装过直接用就好,但是一定放在class里面,不要放在id里面 看见不认识的方法一定要去看里面封装的是什么 之前就是没有看,所以…...
YOLOv8改进 | 主干篇 | ConvNeXtV2全卷积掩码自编码器网络
一、本文介绍 本文给大家带来的改进机制是ConvNeXtV2网络,ConvNeXt V2是一种新型的卷积神经网络架构,它融合了自监督学习技术和架构改进,特别是加入了全卷积掩码自编码器框架和全局响应归一化(GRN)层。我将其替换YOLOv8的特征提取网络,用于提取更有用的特征。经过我的实…...
elasticsearch7.17.9两节点集群改为单节点
需求 将数据从node-23-1节点中迁移到node-83-1节点。但是现在node-83-1并没有加入到集群中,因此首先将node-83-1加入到node-23-1的集群 解决方案 使用ES版本为7.17.9,最开始设置集群为一个节点,node-23-1的配置如下 cluster.name: my-app…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
