简版网络时间服务(SNTP)的实现C#

    /// 
    /// 简单网络时间协议服务器
    /// 
    public class SNTPServer
    {
        int port = 123;             //服务端口,NTP默认端口123
        bool stopFlag = false;      //通知后台线程停止消息循环的标识
        Thread tdServer;            //服务器后台监听线程

        /// 
        /// 初始化一个简单网络时间协议服务器
        /// 
        public SNTPServer()
            : this(123) { }
        /// 
        /// 使用指定参数初始化一个简单网络时间协议服务器
        /// 
        /// 服务端口
        public SNTPServer(int port)
        {
            this.port = port;
        }
        /// 
        /// 获取和设置服务端口号
        /// 
        public int Port
        {
            get { return this.port; }
            set { this.port = value; }
        }
        /// 
        /// 启动服务器
        /// 
        public void Start()
        {
            if (tdServer == null || (!tdServer.IsAlive))
            {
                tdServer = new Thread(bgWork);
                tdServer.IsBackground = true;
                stopFlag = false;
                tdServer.Start();
            }
        }
        /// 
        /// 停止服务器
        /// 
        public void Stop()
        {
            stopFlag = true;
        }

        private void bgWork()
        {
            IPEndPoint iep;
            UdpClient udpclient;
            try
            {
                iep = new IPEndPoint(IPAddress.Any, port);
                udpclient = new UdpClient(iep);
                while (!stopFlag)
                {
                    if (udpclient.Available>0)
                    {
                        byte[] buffer;
                        IPEndPoint remoteipEP = new IPEndPoint(IPAddress.Any, port);
                        buffer = udpclient.Receive(ref remoteipEP);
                        if (buffer.Length >= 48)
                        {
                            NTP.Message msg = (NTP.Message)MarshalExtend.GetObject(buffer, typeof(NTP.Message));
                            if (msg.Mode == NTP.Mode.Client)
                            {
                                NTP.Message reply = new NTP.Message();
                                reply.OriginateTimestamp = msg.TransmitTimestamp;
                                reply.ReceiveTimestamp = DateTime.Now;
                                reply.Mode = NTP.Mode.Server;
                                reply.VersionNumber = 3;
                                reply.LeapIndicator = 0;
                                reply.Stratum = 1;
                                reply.Poll = 0x0A;
                                reply.Precision = 0xE9;
                                reply.RootDelay = 0;
                                reply.RootDispersion = 0;
                                reply.ReferenceIdentifier = BitConverter.ToUInt32(new byte[] { 0x41, 0x43, 0x54, 0x53 }, 0);
                                reply.ReferenceTimestamp = DateTime.Now;
                                reply.TransmitTimestamp = DateTime.Now;
                                buffer = MarshalExtend.GetBytes(reply);
                                udpclient.Send(buffer, buffer.Length, remoteipEP);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.Message, e.Source);
            }
        }
    }

NTP命名空间下,还有几个类

    [StructLayout(LayoutKind.Sequential)]
    class NtpTime
    {
        UInt32 seconds;
        UInt32 fraction;

        static readonly DateTime baseTime = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        public static implicit operator DateTime(NtpTime time)
        {
            /* rfc1305的ntp时间中,时间是用64bit来表示的,记录的是1900年后的秒数(utc格式)
             * 高32位是整数部分,低32位是小数部分 */
            var milliseconds = (int)(((double)ReverseBytes(time.fraction) / uint.MaxValue) * 1000);
            return baseTime.AddSeconds(ReverseBytes(time.seconds)).AddMilliseconds(milliseconds).ToLocalTime();
        }

        public static implicit operator NtpTime(DateTime time)
        {
            NtpTime ntptime = new NtpTime();
            TimeSpan span = DateTime.Now.ToUniversalTime() - baseTime;
            ntptime.seconds = ReverseBytes((uint)span.TotalSeconds);
            ntptime.fraction = ReverseBytes((uint)((span.TotalSeconds - ntptime.seconds) * uint.MaxValue));
            return ntptime;
        }

        // 翻转字节顺序 (32-bit)
        public static UInt32 ReverseBytes(UInt32 value)
        {
            return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
                   (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
        }

        public DateTime DateTime
        {
            get
            {
                return this;
            }
        }
    }
    /// 
    /// 工作模式
    /// 
    public enum Mode : byte
    {
        /// 
        /// 未定义
        /// 
        Unknown = 0,
        /// 
        /// 主动对等体模式
        /// 
        SymmetricActive = 1,
        /// 
        /// 被动对等体模式
        /// 
        SymmetricPassive = 2,
        /// 
        /// 客户端模式
        /// 
        Client = 3,
        /// 
        /// 服务器模式
        /// 
        Server = 4,
        /// 
        /// 广播或组播模式
        /// 
        Broadcast = 5,
        /// 
        /// 控制报文
        /// 
        Control = 6,
        /// 
        /// 预留给内部使用
        /// 
        Reserved = 7
    }
    /// 
    /// NTP报文
    /// 
    [StructLayout(LayoutKind.Sequential)]
    class Message
    {
        byte header;
        byte stratum = 1;       //系统时钟层数
        byte poll = 1;          //轮询时间,即两个连续NTP报文之间的时间间隔
        byte precision = 1;     //系统时钟的精度

        UInt32 rootDelay;       //本地到主参考时钟源的往返时间
        UInt32 rootDispersion;  //系统时钟相对于主参考时钟的最大误差
        UInt32 referenceIdentifier; //参考时钟源的标识

        /// 
        /// 系统时钟最后一次被设定或更新的时间
        /// 
        public NtpTime ReferenceTimestamp { get; set; }
        /// 
        /// 请求报文离开发送端时发送端的本地时间
        /// 
        public NtpTime OriginateTimestamp { get; set; }
        /// 
        /// 请求报文到达接收端时接收端的本地时间
        /// 
        public NtpTime ReceiveTimestamp { get; set; }
        /// 
        /// 应答报文离开应答者时应答者的本地时间
        /// 
        public NtpTime TransmitTimestamp { get; set; }

        public Message()
        {
            header = 0xDB;
        }

        /// 
        /// 获取跳跃指示器
        /// 
        public LeapIndicator LeapIndicator
        {
            get 
            {
                byte val = (byte)(header >> 6);
                switch (val)
                {
                    case 0:
                        return LeapIndicator.NoWarning;
                    case 1:
                        return LeapIndicator.LastMinute61;
                    case 2:
                        return LeapIndicator.LastMinute59;
                    case 3:
                        goto default;
                    default:
                        return LeapIndicator.Alarm;
                }
            }
            set 
            {
                header = (byte)((header & 127) | (((byte)value & 3)) << 6);
            }
        }
        /// 
        /// 获取版本号
        /// 
        public byte VersionNumber
        {
            get 
            {
                byte val = (byte)((header & 0x38) >> 3);
                return val;
            }
            set 
            {
                header = (byte)((header & (255 - 56)) | ((value & 7) << 3));
            }
        }
        /// 
        /// 获取工作模式
        /// 
        public Mode Mode
        {
            get 
            {
                byte val = (byte)(header & 0x7);
                switch (val)
                {
                    case 0:
                        goto default;
                    case 1:
                        return Mode.SymmetricActive;
                    case 2:
                        return Mode.SymmetricPassive;
                    case 3:
                        return Mode.Client;
                    case 4:
                        return Mode.Server;
                    case 5:
                        return Mode.Broadcast;
                    case 6:
                        return Mode.Control;
                    case 7:
                        return Mode.Reserved;
                    default:
                        return Mode.Unknown;
                }
            }
            set
            {
                header = (byte)((header & (255 - 7)) | ((byte)value & 7));
            }
        }
        /// 
        /// 获取系统时钟层数
        /// 
        public byte Stratum
        {
            get
            {
                return this.stratum;
            }
            set
            {
                this.stratum = value;
            }
        }

        public byte Poll
        {
            get { return this.poll; }
            set { this.poll = value; }
        }

        public byte Precision
        {
            get { return this.precision; }
            set { this.precision = value; }
        }

        public uint RootDelay
        {
            get { return this.rootDelay; }
            set { this.rootDelay = value; }
        }

        public uint RootDispersion
        {
            get { return this.rootDispersion; }
            set { this.rootDispersion = value; }
        }

        public uint ReferenceIdentifier
        {
            get { return this.referenceIdentifier; }
            set { this.referenceIdentifier = value; }
        }

    }
    /// 
    /// 跳跃指示器(警告在当月最后一天的最终时刻插入的迫近闰秒)
    /// 
    public enum LeapIndicator : byte
    {
        /// 
        /// No warning
        /// 
        NoWarning = 0,

        LastMinute61 = 1,

        LastMinute59 = 2,
        /// 
        /// 告警状态(时钟未同步)
        /// 
        Alarm = 3
    }

你可能感兴趣的:(技术文章,NTP,网络授时)