Unity通过NTP获取网络时间

最初通过qq时间服务器获得时间,经常出现有网络也获取失败的情况。
后面寻找解决办法,查找资料终于发现通过ntp时间服务器获取网络时间的方法。
 
首先游戏开始获得初始化网络时间,通常只获取一次,其他时间获取时间通过本地时间差加上初始网络时间获得当前时间。
GetCurrentTime()获取当前时间,GetDay()获得当前天数整点。
 
代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;

namespace NTP
{
    public class NetworkTime {

        private static NetworkTime instance;

        private static readonly object locker = new object();

        private NetworkTime(){
        }

        public static NetworkTime GetInstance(){
            if (instance == null) {
                lock (locker) {
                    if (instance == null) {
                        instance = new NetworkTime ();
                    }
                }
            }

            return instance;
        }

        public void InitTime(){
            GetNetworkTime ();
        }
        public string TIME_SERVER_URL = "ntp7.aliyun.com";
        public DateTime initTime,initLocalTime;
        public static DateTime InsteadLocalTime;
        public static string InsteadLocalTime_st;
        public DateTime GetNetworkTime()
        {

            try
            {
                //ntp服务器地址
                string server = TIME_SERVER_URL;

                var ntpData = new byte[48];
                ntpData[0] = 0x1B;
                //网络链接
                var addresses = Dns.GetHostEntry(server).AddressList;
                var ipEndPoint = new IPEndPoint(addresses[0], 123); // https port : 443
                var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                socket.ReceiveTimeout = 5000;
                socket.Connect(ipEndPoint);
                socket.Send(ntpData);
                socket.Receive(ntpData);
                socket.Close();

                ulong intPart = (ulong)ntpData[40] << 24 | (ulong)ntpData[41] << 16 | (ulong)ntpData[42] << 8 | (ulong)ntpData[43];
                ulong fractPart = (ulong)ntpData[44] << 24 | (ulong)ntpData[45] << 16 | (ulong)ntpData[46] << 8 | (ulong)ntpData[47];

                var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
                var networkDataTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Local)).AddMilliseconds((long)milliseconds);

                TimeZone localzone = TimeZone.CurrentTimeZone;
                TimeSpan currentOffset = localzone.GetUtcOffset(networkDataTime);
                initTime = networkDataTime + currentOffset;
                initLocalTime = DateTime.Now; 
                Debug.Log("steve" + initTime.ToString());
                return initTime;

            }
            catch
            {

                InsteadLocalTime = DateTime.UtcNow;

                TimeZone localzone_ = TimeZone.CurrentTimeZone;
                TimeSpan currentOffset_ = localzone_.GetUtcOffset(DateTime.UtcNow);
                initTime = DateTime.UtcNow + currentOffset_;//기준 시에 +,- 로컬과 시간차이 더하면 현지로컬시간이 나옴!
                return initTime;

            }

        }

        public DateTime GetDay(int day = 0){

            return GetCurrentTime().AddDays(day).Date;
        }

        public DateTime GetCurrentTime(){
            DateTime d = DateTime.Now;
            return initTime + (d - initLocalTime);
        }

        public void CompareGameTime(){
            //时间的比较,一般用于连续签到系统等
            string SavedAfterDayTime = PlayerPrefs.GetString("SavedAfterDayTime", "11/30/2018 00:00:00 AM");
            //转化成第一个时间点(即领取后的第一天)
            DateTime SavedAfterDayTime_T = Convert.ToDateTime(SavedAfterDayTime);
            //当前时间与时间点相比较,当前时间超过存档钱则等于1,相等则等于0,当前时间未超过存档点的时间则等于-1
            int compare1 = DateTime.Compare(GetDay(), SavedAfterDayTime_T.Date);

            if(compare1 < 0){
                //开启倒计时
            }else if(compare1 == 0){
                //待领取,计时器结束
            }else{
                //重置状态

            }

        }
            
    }
}
原文地址:https://www.cnblogs.com/txfd/p/10051652.html