根据Time Protocol从NIST Internet Time Servers获取准确时间
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获取准确时间的更多相关文章
- Java获取NTP网络时间
最近项目中涉及到一个时间验证的问题,需要根据当前时间来验证业务数据是否过期.所以直接写代码如下: new java.util.Date().getTime(); 结果测试的时候出现了 ...
- 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 ...
- Common Internet File System
CIFS (Common Internet File System) is a protocol that gained popularity around the year 2000, as ven ...
- 【计算机网络】-网络层-Internet的网络层
[计算机网络]-网络层-Internet的网络层 Internet是一组相互连接的网络或者自治系统的集合 Internet 1.存在几个主要骨干网络,骨干网络是由高带宽的线路和快速路由器构成 2.这些 ...
- 《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- [Database] Deadlock avoidance protocol
如何避免Deadlock,如果我们能提前知道各个Process对于资源的需求情况,我们就可以用Banker's algorithm (银行家算法) 来解决问题.可是这在现在中不好实现,因为很难提前知道 ...
- Kafka系列之-Kafka Protocol实例分析
本文基于A Guide To The Kafka Protocol文档,以及Spark Streaming中实现的org.apache.spark.streaming.kafka.KafkaClust ...
- Protocol Buffer学习笔记
Protocol Buffer Protobuf基础概念 Protobuf是google开发的数据结构描述语言,能够将结构化数据序列化与反序列化,取代json和xml,常用于服务器通信协议.RPC系统 ...
- https那些事儿
(一)SSL/TLS协议运行机制的概述 一.作用 不使用SSL/TLS的HTTP通信,就是不加密的通信.所有信息明文传播,带来了三大风险. (1) 窃听风险(eavesdropping):第三方可以获 ...
随机推荐
- ansible 之条件语句 when
注册变量: 变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的playbook使用.例如: - hosts: webservers tasks: - shell: /usr/bin/foo ...
- java中的引用类型 部分讲解
所谓的引用类型 类--接口--数组--枚举 [01--Scanner类] Scanner 这个类是用于键盘输入 它的格式为 类型 对象名称 = new 类型(): 它的操作格式 对象名.nex ...
- 给洛谷填坑的spj……
这里提供了洛谷某些题的$special\ judge$,供需要的oier拿过去对拍. 1.P3825 #include "testlib.h" using namespace st ...
- 安装zlib的过程(Compression requires the (missing) zlib module)(Python2.6升级为2.7出现的问题)
觉得有必要把解决问题的过程写下来 1,因为要安装flask,所以安装pip,所以安装setuptools,所以安装zlib.(具体过程http://www.cnblogs.com/aiyr/p/726 ...
- 酱油 Noip2018颓废记
也不知道写一些什么了 凑和着写写吧 最近十分的¥#&(^ --#%!*%¥^#$# Day -1 上午考了一场试 就\(TM\)考了60分 好不容易积攒起来的信心啊~~~~~~ 就这么垮了~~ ...
- 数据结构基础 ---- 数组的理解和实现(Java)
什么是数组 数组是由类型相同的数据元素构成的有序集合,每个元素称为数组元素,每个元素受n(n>= 1)个线性关系的约束,每个元素在n个线性关系中的序号i1, i2, ....., in称该元素的 ...
- vim中常用的命令
1.光标的命令 gg 移到第一行位置 G 移到最后一行 o 行首 $ 行末 nk 向上移动n行 nj 向下移动n行 nh 向左移动n列 nl 向右移动n列 ctrl+f ...
- QuantLib 金融计算——数学工具之数值积分
目录 QuantLib 金融计算--数学工具之数值积分 概述 常见积分方法 高斯积分 如果未做特别说明,文中的程序都是 Python3 代码. QuantLib 金融计算--数学工具之数值积分 载入模 ...
- CSS03--框模型、定位position、浮动
我们接着“CSS02”,继续学习一些新的样式属性. 1.框模型: 规定了元素框处理 元素内容.内边距(padding).边框(border).外边距(margin,可以是负值)的方式 2.内边距 ...
- Stopwatch类学习
1.概述:给一条大MSDN的链接关于Stopwatch类最详细的教程 ,然后看着教程自己手动敲一边,加深映象,好记性不如烂键盘,哈哈,开个玩笑! 2.类位置:这个类在哪里,这个是重点,虽然C#IDE很 ...