转自: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));
}
}