当前位置: 首页 > news >正文

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(网络时间协议&#xff08;Network Time Protocol&#xff09;)来获取时间&#xff0c;所以我们需要一个特别的方式来获取分布式系统中的时间&#xff0c;mvcc也是使用time保证读…...

人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新

随着科技的飞速发展&#xff0c;人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新。富唯智能移动机器人&#xff0c;以其独特的3D视觉技术&#xff0c;赋予了移动机器人一双“智慧之眼”&#xff0c;从而为现代工业自动化带来了前所未有的突破。 富唯智能移动机器…...

NSSCTF 简单包含

开启环境: 使用POST传flag&#xff0c;flag目录/var/www/html/flag.php 先使用post来尝试读取该flag.php 没反应: 查看一下源码index.php&#xff0c;看有什么条件 base64解密: <?php$path $_POST["flag"];if (strlen(file_get_contents(php://input)) <…...

FlinkSQL处理Canal-JSON数据

背景信息 Canal是一个CDC&#xff08;ChangeLog Data Capture&#xff0c;变更日志数据捕获&#xff09;工具&#xff0c;可以实时地将MySQL变更传输到其他系统。Canal为变更日志提供了统一的数据格式&#xff0c;并支持使用JSON或protobuf序列化消息&#xff08;Canal默认使用…...

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— DevEco Studio下载与安装

一、下载DevEco Studio IDE开发工具 1. 登录鸿蒙官网 网址为&#xff1a; ​​​​​​​华为HarmonyOS智能终端操作系统官网 | 应用设备分布式开发者生态 页面如下&#xff1a; 2. 搜索“DevEco Studio IDE” 点击右上角的“请输入关键词”&#xff0c;在其中搜索“DevEc…...

大模型上下文长度的超强扩展:从LongLora到LongQLora

前言 本文一开始是《七月论文审稿GPT第2版&#xff1a;从Meta Nougat、GPT4审稿到Mistral、LongLora Llama》中4.3节的内容&#xff0c;但考虑到 一方面&#xff0c;LongLora的实用性较高二方面&#xff0c;为了把LongLora和LongQLora更好的写清楚&#xff0c;而不至于受篇幅…...

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循环遍历,动态赋值类名并配置不同颜色

需求&#xff1a;后端要传入不同的等级&#xff0c;前端通过等级展示不同的字体颜色&#xff0c;通过scss遍历更有利于动态修改颜色或者增删等级 1.通过 for $i from 1 through 4 定义循环&#xff0c;索引值为i 2.nth($colors, $i) 取出对应的颜色 $colors: #ff0000, #00ff…...

GaussDB数据库使用COPY命令导数

目录 一、前言 二、GaussDB数据库使用COPY命令导数语法 1、语法COPY FROM 2、语法COPY TO 3、特别说明及参数示意 三、GaussDB数据库使用COPY命令导数示例 1、操作步骤 2、准备工作&#xff08;示例&#xff09; 3、把一个表的数据拷贝到一个文件&#xff08;示例&…...

SunFMEA软件免费试用:FMEA的目标和限制是什么?

免费试用FMEA软件-免费版-SunFMEA FMEA&#xff0c;即故障模式与影响分析&#xff0c;是一种预防性的质量工具&#xff0c;旨在识别、评估和优先处理潜在的故障模式及其对系统性能的影响。其目标是提高产品和过程的可靠性和安全性&#xff0c;降低产品故障的风险&#xff0c;并…...

【Redis交响乐】Redis中的数据类型/内部编码/单线程模型

文章目录 一. Redis中的数据类型和内部编码二. Redis的单线程模型面试题: redis是单线程模型,为什么效率之高,速度之快呢? 在上一篇博客中我们讲述了Redis中的通用命令,本篇博客中我们将围绕每个数据结构来介绍相关命令. 一. Redis中的数据类型和内部编码 type命令实际返回的…...

APK 瘦身

APK 瘦身的主要原因是考虑应用的下载转化率和留存率&#xff0c;应用太大了&#xff0c;用户可能就不下载了。再者&#xff0c;因为手机空间问题&#xff0c;用户有可能会卸载一些占用空间比较大的应用&#xff0c;所以&#xff0c;应用的大小也会影响留存率。 1 APK 的结构 …...

GitHub上的15000个Go模块存储库易受劫持攻击

内容概要&#xff1a; 目前研究发现&#xff0c;GitHub上超过15000个Go模块存储库容易受到一种名为“重新劫持”的攻击。 由于GitHub用户名的更改会造成9000多个存储库容易被重新劫持&#xff0c;同时因为帐户删除&#xff0c;会对6000多个存储库造成重新劫持的危机。目前统计…...

避免3ds Max效果图渲染一片黑的4个正确解决方法

在进行3ds Max效果图渲染时&#xff0c;有时候会遇到渲染一片黑的情况&#xff0c;这给我们的工作带来了很大的困扰。为了解决这个问题&#xff0c;下面我将介绍4个正确的解决方法。 1.相机位置 首先需要考虑场景内的相机位置是否有问题。如果相机放在了模型的内部或者墙体的外…...

UI演示双视图立体匹配与重建

相关文章&#xff1a; PyQt5和Qt designer的详细安装教程&#xff1a;https://blog.csdn.net/qq_43811536/article/details/135185233?spm1001.2014.3001.5501Qt designer界面和所有组件功能的详细介绍&#xff1a;https://blog.csdn.net/qq_43811536/article/details/1351868…...

添加一个编辑的小功能(PHP的Laravel)

一个编辑的按钮可以弹出会话框修改断更天数 前台 加一个编辑按钮的样式&#xff0c;他的名字是固定好的 之前有人封装过直接用就好&#xff0c;但是一定放在class里面&#xff0c;不要放在id里面 看见不认识的方法一定要去看里面封装的是什么 之前就是没有看&#xff0c;所以…...

YOLOv8改进 | 主干篇 | ConvNeXtV2全卷积掩码自编码器网络

一、本文介绍 本文给大家带来的改进机制是ConvNeXtV2网络,ConvNeXt V2是一种新型的卷积神经网络架构,它融合了自监督学习技术和架构改进,特别是加入了全卷积掩码自编码器框架和全局响应归一化(GRN)层。我将其替换YOLOv8的特征提取网络,用于提取更有用的特征。经过我的实…...

elasticsearch7.17.9两节点集群改为单节点

需求 将数据从node-23-1节点中迁移到node-83-1节点。但是现在node-83-1并没有加入到集群中&#xff0c;因此首先将node-83-1加入到node-23-1的集群 解决方案 使用ES版本为7.17.9&#xff0c;最开始设置集群为一个节点&#xff0c;node-23-1的配置如下 cluster.name: my-app…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...