Time Protocol(RFC-868)是一种非常简单的应用层协议:它返回一个32位的二进制数字,这个数字描述了从1900年1月1日0时0分0秒到现在的秒数,服务器在TCP的37号端口监听时间协议请求。本函数将服务器返回值转化成本地时间。

先前不知道有现成的IPAddress.NetworkToHostOrder函数,所以自己直接写了个ReverseBytes函数,把字节数组从Big-endian转换为Little-endian。这个函数可能在其他地方也有用,所以索性就留着了。

         private const int BUFSIZE = ;      //字符数组的大小
private const int PORT = ; //服务器端口号
private const int TIMEOUT = ; //超时时间(毫秒)
private const int MAXTRIES = ; //尝试接受数据的次数 /// <summary>
/// 从NIST Internet Time Servers获取准确时间。
/// </summary>
/// <param name="dateTime">返回准确的本地时间</param>
/// <param name="timeServer">服务器列表</param>
/// <returns>获取时间失败将返回false,否则返回true</returns>
public static bool GetDateTimeFromTimeServer(out DateTime now, string timeServers = "time.nist.gov")
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//设置获取超时时间
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, TIMEOUT); byte[] rcvBytes = new byte[BUFSIZE]; //接收数据的字节数组
int tries = ; //记录尝试次数
bool received = false; //接收是否成功
int totalBytesRcvd = ; //总共接收的字节数
int bytesRcvd = ; //本次接收的字节数
do
{
try
{
socket.Connect(Dns.GetHostEntry(timeServers).AddressList, PORT);
while ((bytesRcvd = socket.Receive(rcvBytes, totalBytesRcvd, BUFSIZE - totalBytesRcvd, SocketFlags.None)) > )
{
totalBytesRcvd += bytesRcvd;
}
received = true;
}
catch (SocketException)
{
//超时或者其他Socket错误,增加参数次数
tries++;
}
} while ((!received) && (tries < MAXTRIES));
socket.Close(); if (received)
{
//将字节数组从Big-endian转换为Little-endian
//ReverseBytes(ref rcvBytes, 0, 4);
//UInt32 seconds = BitConverter.ToUInt32(rcvBytes, 0);
UInt32 seconds = BitConverter.ToUInt32(rcvBytes, );
if (BitConverter.IsLittleEndian)
{
seconds = (UInt32)IPAddress.NetworkToHostOrder((int)seconds);
}
//从1900年1月1日0时0分0秒日期加上获取的秒数并转换到当前本地时区时间
now = new DateTime(, , , , , , DateTimeKind.Utc).AddSeconds(seconds).ToLocalTime();
return true;
}
else
{
now = DateTime.Now;
return false;
}
} /// <summary>
/// 翻转byte数组的字节顺序
/// </summary>
/// <param name="bytes">要翻转的字节数组</param>
/// <param name="start">规定转换起始位置</param>
/// <param name="len">要翻转的长度</param>
private static void ReverseBytes(ref byte[] bytes, int start, int len)
{
if ((start < ) || (start > bytes.Length - ) || (len > bytes.Length))
{
throw new ArgumentOutOfRangeException();
} int end = start + len - ;
if (end > bytes.Length)
{
throw new ArgumentOutOfRangeException();
} byte tmp;
for (int i = , index = start; index < start + len / ; index++, i++)
{
tmp = bytes[end - i];
bytes[end - i] = bytes[index];
bytes[index] = tmp;
}
}

代码未经过严格测试,如果有什么错误,欢迎指出,谢谢!

参考文献

[1]陈香凝,王烨阳,陈婷婷,张铮.Windows网络与通信程序设计第三版[M].人民邮电出版社,2017:27-28.

[2]D.Makofske,M.Donahoo,K.Calvert.TCPIP Sockets in C# Practical Guide for Programmers[M].Morgan Kaufmann.2004。

[3]NIST Internet Time Servers.http://tf.nist.gov/tf-cgi/servers.cgi.

根据Time Protocol从NIST Internet Time Servers获取准确时间的更多相关文章

  1. Java获取NTP网络时间

    最近项目中涉及到一个时间验证的问题,需要根据当前时间来验证业务数据是否过期.所以直接写代码如下: new java.util.Date().getTime();          结果测试的时候出现了 ...

  2. Websocket 与代理服务器如何交互? How HTML5 Web Sockets Interact With Proxy Servers

    How HTML5 Web Sockets Interact With Proxy Servers Posted by Peter Lubberson Mar 16, 2010 With the re ...

  3. Common Internet File System

    CIFS (Common Internet File System) is a protocol that gained popularity around the year 2000, as ven ...

  4. 【计算机网络】-网络层-Internet的网络层

    [计算机网络]-网络层-Internet的网络层 Internet是一组相互连接的网络或者自治系统的集合 Internet 1.存在几个主要骨干网络,骨干网络是由高带宽的线路和快速路由器构成 2.这些 ...

  5. 《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  6. [Database] Deadlock avoidance protocol

    如何避免Deadlock,如果我们能提前知道各个Process对于资源的需求情况,我们就可以用Banker's algorithm (银行家算法) 来解决问题.可是这在现在中不好实现,因为很难提前知道 ...

  7. Kafka系列之-Kafka Protocol实例分析

    本文基于A Guide To The Kafka Protocol文档,以及Spark Streaming中实现的org.apache.spark.streaming.kafka.KafkaClust ...

  8. Protocol Buffer学习笔记

    Protocol Buffer Protobuf基础概念 Protobuf是google开发的数据结构描述语言,能够将结构化数据序列化与反序列化,取代json和xml,常用于服务器通信协议.RPC系统 ...

  9. https那些事儿

    (一)SSL/TLS协议运行机制的概述 一.作用 不使用SSL/TLS的HTTP通信,就是不加密的通信.所有信息明文传播,带来了三大风险. (1) 窃听风险(eavesdropping):第三方可以获 ...

随机推荐

  1. Impala源码之订阅发布系统的实现

    本文由  网易云发布. 作者:冯宇 本篇文章仅限内部分享,如需转载,请联系网易获取授权. 本文是Impala源码笔记的第一篇,本文主要根据源代码学习一下statestored模块的实现,众所周知,Im ...

  2. 【JVM】jvm启动参数

    -server -Xmx2048m -Xms1500m -Xmn1024m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConc ...

  3. 谷歌将对欧洲 Android 设备制造商收取其应用服务费用

    简评:欧盟就谷歌违反了<反垄断法>开出天价罚单,导致谷歌运营生态被打破,为了配合这一裁决,谷歌将调整其运营模式.欧盟似乎赢了,而这最后买单的却是消费者. 今年七月份,谷歌要求 Androi ...

  4. windows10 pip install MySQL-python mysqlclient

    https://dev.mysql.com/downloads/connector/python/ 到上述地址下载对应系统的驱动程序安装即可. 安装mysqlclient方法如下: https://w ...

  5. MFC Windows程序开发究竟是什么?

    MFC Windows程序开发究竟是什么? MFC是一个Application Framework.他是一个完整的程序模型. 什么是MFC?MFC是微软公司出品一个Application Framew ...

  6. leetcode-840-Magic Squares In Grid

    题目描述: A 3 x 3 magic square is a 3 x 3 grid filled with distinct numbers from 1 to 9 such that each r ...

  7. Tensorflow入门----占位符、常量和Session

    安装好TensorFlow之后,开一个python环境,就可以开始运行和使用TensorFlow了. 先给一个实例, #先导入TensorFlow import tensorflow as tf he ...

  8. Python【每日一问】17

    问: [基础题]:简述Python的异常处理机制[提高题]:请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%2 ...

  9. Oracle 11g

    Oracle 11g 第一章  Oracle 11g数据库简介 1.1  认识Oracle11g Oracle 11g是Oracle 数据库最新的版本,目前已经被企业广泛的应用. 1.2  Oracl ...

  10. 阿里云 下载的 apache 证书 转换为 pcks8 证书

    第一步: 百度 搜索  rsa 转 pcks8 将 .key 文件 转换成 pcks8.key . 第二部: 将 chain.crt 的 内容 复制到 public.crt 下方.. 新的 publi ...