当前位置: 首页 > 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}
}
http://www.lryc.cn/news/272791.html

相关文章:

  • ArduPilot开源代码之MatekSys Optical Flow 3901-L0X
  • 【时钟】分布式时钟HLC|Logical Time|Vector Clock|True Time
  • 人工智能AI与3D视觉技术的结合正在引领新一代移动机器人的革新
  • NSSCTF 简单包含
  • FlinkSQL处理Canal-JSON数据
  • 玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— DevEco Studio下载与安装
  • 大模型上下文长度的超强扩展:从LongLora到LongQLora
  • pdf格式转换为txt格式
  • scss使用for循环遍历,动态赋值类名并配置不同颜色
  • GaussDB数据库使用COPY命令导数
  • SunFMEA软件免费试用:FMEA的目标和限制是什么?
  • 【Redis交响乐】Redis中的数据类型/内部编码/单线程模型
  • APK 瘦身
  • GitHub上的15000个Go模块存储库易受劫持攻击
  • 避免3ds Max效果图渲染一片黑的4个正确解决方法
  • UI演示双视图立体匹配与重建
  • 添加一个编辑的小功能(PHP的Laravel)
  • YOLOv8改进 | 主干篇 | ConvNeXtV2全卷积掩码自编码器网络
  • elasticsearch7.17.9两节点集群改为单节点
  • 二叉树的层序遍历,力扣
  • 构建Dockerfile报错/bin/sh: 1: cd: can‘t cd to /xxx/yyy问题记录
  • Vue常用的修饰符详解(有哪些,怎么用)
  • Linux C/C++ 获取CPUID
  • 2023年“中银杯”安徽省网络安全B模块(部分解析)
  • 194.【2023年华为OD机试真题(C卷)】单行道汽车通行时间(迭代计算—JavaPythonC++JS实现)
  • 第二证券机构策略:股指预计维持蓄势震荡格局 关注煤炭、电力等板块
  • Go 泛型之泛型约束
  • 【数据仓库与联机分析处理】数据仓库
  • 机器学习:贝叶斯估计在新闻分类任务中的应用
  • [C#]基于deskew算法实现图像文本倾斜校正