×

Unity联网状态下获取网络时间否则获取本地时间,用于Unity程序倒计时和显示时间

Kalet Kalet 发表于2023-09-01 12:08:01 浏览438 评论0

抢沙发发表评论

转自:Unity联网状态下获取网络时间否则获取本地时间,用于Unity程序倒计时和显示时间_weixin_44047050的博客-CSDN博客


using System;

using System.Net;

using UnityEngine;


public class GetCurrentTime : MonoBehaviour

{

    private void Start()

    {

        DateTime currentTime;


        if (Application.internetReachability != NetworkReachability.NotReachable)

        {

            // 如果连接到互联网,则获取网络时间

            currentTime = GetNetworkTime();

        }

        else

        {

            // 如果没有连接到互联网,则获取本地时间

            currentTime = DateTime.Now;

        }


        Debug.Log("当前时间:" + currentTime);

    }


    private DateTime GetNetworkTime()

    {

        try

        {

            // 从 NTP Pool Project 获取网络时间

            const string ntpServer = "pool.ntp.org";

            var ntpData = new byte[48];// 创建一个 48 字节大小的字节数组来存储 NTP 数据

            ntpData[0] = 0x1B;// 将 NTP 数据的第一个字节设置为 0x1B,这是 NTP 协议的请求数据格式


            var addresses = Dns.GetHostEntry(ntpServer).AddressList;// 获取 NTP 服务器的 IP 地址列表

            var ipEndPoint = new IPEndPoint(addresses[0], 123);// 创建用于连接的 IP 端点,使用第一个 IP 地址和 NTP 服务器的端口 123

            var socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);// 创建套接字,使用 IPv4 地址族、数据报套接字类型和 UDP 协议类型


            socket.Connect(ipEndPoint);// 连接到 NTP 服务器

            socket.Send(ntpData);// 发送 NTP 数据

            socket.Receive(ntpData);// 接收 NTP 响应数据

            socket.Close();// 关闭套接字连接


            const byte serverReplyTime = 40;// 服务器响应时间在 NTP 数据中的偏移量

            ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);// 从 NTP 数据中获取无符号 32 位整数部分

            ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);// 从 NTP 数据中获取无符号 32 位小数部分

             // 交换整数部分和小数部分的字节顺序,以适应本地字节顺序

            intPart = SwapEndianness(intPart);

            fractPart = SwapEndianness(fractPart);

           

            var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);// 将整数部分和小数部分转换为毫秒数

            var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);// 根据毫秒数计算网络时间(从 1900 年 1 月 1 日开始计算)


            return networkDateTime;

        }

        catch (Exception e)

        {

            Debug.LogWarning("获取网络时间失败: " + e.Message);

            return DateTime.Now;

        }

    }

 // 交换字节顺序,将大端序转换为小端序或反之

    private static uint SwapEndianness(ulong x)

    {

        return (uint)(((x & 0x000000ff) << 24) +

                       ((x & 0x0000ff00) << 8) +

                       ((x & 0x00ff0000) >> 8) +

                       ((x & 0xff000000) >> 24));

    }

}




群贤毕至

访客