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}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c# OpenCvSharp Cv2.Threshold()和Cv2.AdaptiveThreshold参数说明

一、 Cv2.Threshold()二值化的函数参数说明 Cv2.Threshold()是一个用于图像二值化的函数。具体来说&#xff0c;它会将图像中的每一个像素的灰度值与一个阈值进行比较&#xff0c;大于该阈值的像素会被赋值为最大灰度值(即 255)&#xff0c;小于该阈值的像素会被赋值为最小灰度…

Apollo感知模块 :传感器| 目标监测| 障碍物识别 | 模型管理

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 粉丝福利活动 ✅参与方式&#xff1a;通过连接报名观看课程&#xff0c;即可免费获取精美周边 ⛳️活动链接&#xf…

用c语言以升序顺序显示15个单词,从键盘上输入15个单词,将其以升序顺序显示出来。(排序方法不限,单词不得雷同,而且单词须是正确的单词)

用c语言以升序顺序显示15个单词,从键盘上输入15个单词&#xff0c;将其以升序顺序显示出来。&#xff08;排序方法不限&#xff0c;单词不得雷同,而且单词须是正确的单词&#xff09; 以下是一个使用C语言实现的示例程序&#xff0c;可以从键盘上输入15个单词&#xff0c;并将它…

简易机器学习笔记(八)关于经典的图像分类问题-常见经典神经网络LeNet

前言 图像分类是根据图像的语义信息对不同类别图像进行区分&#xff0c;是计算机视觉的核心&#xff0c;是物体检测、图像分割、物体跟踪、行为分析、人脸识别等其他高层次视觉任务的基础。图像分类在许多领域都有着广泛的应用&#xff0c;如&#xff1a;安防领域的人脸识别和…

视频号频繁显眼!是资本的运作?还是互联网新风口到来?

视频号这个平台出现了&#xff0c;特别是在最近存在感越来越强&#xff0c;而且已经有些人开始在视频号当中购物了&#xff0c;这也就意味着&#xff0c;视频号电商出现了&#xff0c;腾讯也开始搞电商了。 很多人可能对视频号做电商这个事情呢&#xff0c;抱有一定的迟疑态度&…

【算法】数论---约数

约数里面的一个重要性质&#xff1a;一个数的约数都是成对存在的(以sqrt(x)为分界线) 一、求一个数的所有约数---试除法 int x; cin>>x; int yue[10000]{0},idx0; for(int i1;i<x/i;i) {if(x%i0){yue[idx]i;cout<<i<<" ";} }for(int iidx-1;i&…

深度学习:大规模模型分布式训练框架DeepSpeed

深度学习&#xff1a;大规模模型分布式训练框架DeepSpeed DeepSpeed简介DeepSpeed核心特点DeepSpeed如何工作&#xff1f;DeepSpeed如何使用&#xff1f;参考文献 DeepSpeed简介 随着机器学习模型变得越来越复杂和庞大&#xff0c;训练这些模型所需的计算资源也在不断增加。特别…

九州金榜|家庭教育小妙招如何培养孩子学习习惯

做小学老师的时候&#xff0c;很多家长都问过我同一个问题&#xff0c;孩子成绩差&#xff0c;如何提高孩子的成绩&#xff1f; 好像成绩是我们的家长判断孩子是否优秀的唯一标准&#xff0c;一切都是围绕着成绩说话&#xff0c;考好了表扬、鼓励&#xff0c;考不好就会被批评…

【UE5.1】给森林添加天气效果

在上一篇博客&#xff08;【UE5.1】程序化生成Nanite植被&#xff09;基础上给森林添加天气交互效果&#xff0c;角色和雪地、水坑的交互效果。 目录 效果 步骤 一、准备工作 二、添加超动态天空 2.1 修改时间 2.2 昼夜交替 三、添加超动态天气 3.1 改变天气 3.2 …

uniCloud 云数据库(新建表、增、删、改、查)

新建表结构描述文件 todo 为自定义的表名 表结构描述文件的默认后缀为 .schema.json 设置表的操作权限 uniCloud-aliyun/database/todo.schema.json 默认的操作权限都是 false "permission": {"read": false,"create": false,"update&quo…

html中的form表单以及相关控件input、文本域、下拉select等等的详细解释 ,点赞加关注持续更新~

文章目录 表单创建表单forminput 标签input标签的value属性设置input标签格式单选框多选框上传文件下拉菜单文本域设置文本域格式label 标签按钮 表单 作用&#xff1a;收集用户信息。 使用场景&#xff1a; 登录页面注册页面搜索区域 创建表单form <form action".…

DataGear 4.7.0 发布,数据可视化分析平台

DataGear专业版 1.0.0 正式发布&#xff0c;欢迎试用&#xff01; http://datagear.tech/pro/ DataGear 4.7.0 发布&#xff0c;严重漏洞和BUG修复&#xff0c;具体更新内容如下&#xff1a; 新增&#xff1a;HTTP数据集新增【编码请求地址】支持&#xff0c;可用于解决请求…

希亦、觉飞、小吉三款婴儿洗衣机大比拼!全方位对比测评

由于年龄幼小的婴儿的皮肤都非常的幼嫩&#xff0c;因此婴儿衣物材质的类型大部分都是采用为纯棉&#xff0c;并且婴儿的衣物不能够与大人的衣物一起进行混洗&#xff0c;容易把细菌感染到宝宝的衣物上&#xff0c;因此很多家庭为了保证宝宝衣服的有效清洁&#xff0c;避免交叉…

TXT文本删除第一行文本变成空要如何解决呢

首先大家一起来看下这个TXT文本里面有多行内容&#xff0c;想把开头第一行批量删除不要掉。 1..如果是一两个本可以手动删除也很方便哦&#xff0c;如果文本量比较大如几十几、几百个文本大家一直都选用《首助编辑高手》工具去批量操作哦。批量操作可以大大提高工作效率。接来看…

AI实景无人直播创业项目:开启自动直播新时代,一部手机即可实现财富增长

在当今社会&#xff0c;直播已经成为了人们日常生活中不可或缺的一部分。无论是商家推广产品、明星互动粉丝还是普通人分享生活&#xff0c;直播已经渗透到了各行各业。然而&#xff0c;传统直播方式存在着一些不足之处&#xff0c;如需现场主持人操作、高昂的费用等。近年来&a…

Minitab 各版本安装指南

Minitab下载链接 https://pan.baidu.com/s/1PLqocknkoRGGI9lbV3e45A?pwd0531 1.鼠标右击【Minitab 21(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;选择【解压到 Minitab 21(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【setu…

MacOS - 苹果电脑程序还能正常启动,但图标消失不见了~

问题描述 网上有一些解决方案说是 killall Finder 命令&#xff0c;重置 Docker 等等&#xff0c;但是发现还是不行&#xff0c;于是必杀技…… 解决方案 方案一、删除该 App&#xff0c;重装即可方案二、如果懒得重装&#xff0c;可以在 Finder 中找到对应的应用程序&#xf…

如何把照片多余的地方擦除?一键消除图片上的瑕疵,简单又轻松,太方便了

在数字繁荣的时代&#xff0c;图片处理已然成为我们生活乐章中不可或缺的一部分&#xff0c;就如画师手中的画笔般灵动&#xff0c;摄影师镜头下的世界般多彩。然而&#xff0c;在捕捉或获取这些美丽的图片时&#xff0c;可能会不小心闯入一些不速之客&#xff0c;给画面带来瑕…

听GPT 讲Rust源代码--compiler(3)

File: rust/compiler/rustc_codegen_cranelift/src/value_and_place.rs 在Rust的编译器源代码中&#xff0c;rust/compiler/rustc_codegen_cranelift/src/value_and_place.rs文件扮演着重要的角色。它包含了与值和位置&#xff08;Place&#xff09;相关的实现和结构体定义&…

非常不错的SSH工具

Tabby 官网地址&#xff1a; Tabby - a terminal for a more modern age GitHub地址&#xff1a; GitHub - Eugeny/tabby: A terminal for a more modern age 使用说明&#xff1a; Xterminal 使用说明地址&#xff1a; 一款颜值、功能都很能打的 SSH 工具 官方地址&…