首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >占用空间小,无需NTP即可实现时钟同步

占用空间小,无需NTP即可实现时钟同步
EN

Stack Overflow用户
提问于 2011-04-13 07:50:52
回答 6查看 4.3K关注 0票数 14

我正在寻找一种简单的时钟同步协议,它很容易实现,占用空间小,并且在没有互联网连接的情况下也可以工作,这样它就可以在封闭的实验室网络中使用。需要说明的是,我要找的不是可以用来对事件进行排序的东西(比如矢量时钟),而是可以让不同节点上的进程根据本地时钟同步它们的操作的东西。据我所知,这需要一个可以考虑时钟漂移的解决方案。可以假定存在TCP/IP或类似的相对低延迟的流连接。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-05-19 13:38:18

免责声明:无论如何我都不是NTP专家。只是一个业余爱好者在周末找乐子。

我知道您说过您不想要NTP实现,因为您的环境中可能没有可用的Internet NTP服务器。

但是,简化的NTP查找可能很容易实现,如果您有本地NTP服务器,则可以实现良好的同步。

下面是操作步骤:

回顾RFC 5905

您将看到NTP v4数据包如下所示:

  • LI (2位)
  • VN (3位)-使用'100‘(4)
  • 模式(3位)
  • 层(8位)

H110轮询(8 bits)

  • Precision (8位)H213H114根延迟(32位)

H116根分散(32 bits)

  • Reference Id (32位)时间戳(64位)

H122原始时间戳(64位)(64 bits)

  • Transmit时间戳(64 bits)
  • Extension字段1 (variable)
  • Extension字段2 (variable)
  • ...
  • Key Identifier
  • Digest (128位)

摘要不是必需的,因此形成有效的客户端请求非常容易。按照RFC中的指导,使用LI = '00',VN = '100‘(十进制4),Mode = '011’(十进制3)。

使用C#来说明:

代码语言:javascript
运行
复制
byte[] ntpData = new byte[48]
Array.Clear(ntpData, 0, ntpData.Length);
ntpData[0] = 0x23;  // LI = 00, VN = 100, Mode = 011

打开到目标服务器的套接字并将其发送过来。

代码语言:javascript
运行
复制
int ntpPort = 123;
IPEndPoint target = new IPEndPoint(Dns.GetHostEntry(serverDnsName).AddressList[0], ntpPort);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.Connect(target);
s.Send(ntpData);

在响应中,当前时间将在传输时间戳中(字节40 - 48)。时间戳是64位无符号定点数字。整数部分是前32位,小数部分是最后32位。它表示从1900年1月1日0h开始的秒数。

代码语言:javascript
运行
复制
s.Receive(ntpData);
s.Close();

ulong intPart = 0;
ulong fractPart = 0;

for (int i = 0; i < 4; i++)
    intPart = (intPart << 8) | ntpData[40 + i];

for (int i = 4; i < 8; i++)
    fractPart = (fractPart << 8) | ntpData[40 + i];

要以(大致)秒的粒度更新时钟,可以使用:# of use 0hJan-1-1900= intPart + (fractPart / 2^32)。(我说大致是因为没有考虑网络延迟,我们在这里进行四舍五入)

代码语言:javascript
运行
复制
ulong seconds = intPart + (fractPart / 4294967296);

TimeSpan ts = TimeSpan.FromTicks((long)seconds * TimeSpan.TicksPerSecond);

DateTime now = new DateTime(1900, 1, 1);
now = DateTime.SpecifyKind(now, DateTimeKind.Utc);
now += ts;

" now“现在是具有当前时间的DateTime,单位为UTC。

虽然这可能不能回答您的问题,但希望它能让NTP不那么不透明。=)

票数 11
EN

Stack Overflow用户

发布于 2011-05-19 21:42:48

仅基于维基百科的文章,我就能够非常快速和轻松地实现精确时间协议的精简版本。如果你所感兴趣的是使它们彼此同步,而不是让它们与外部世界同步,那么你应该能够以最小的努力获得毫秒级的精度。

该协议的基本内容包括:

  1. 主时钟广播同步消息,其时间戳为发送消息时的时间戳(T1)。
  2. 客户端将接收同步消息的时间记录为T1‘。
  3. 客户端将延迟请求发送回主时钟,并将发送消息的时间记录为T2。
  4. 主时钟以接收消息的时间响应延迟请求。此时间为T2‘。
  5. Client通过( T1’-T1-T2‘+T2)/2调整其时钟。

如果您需要更好的稳定性,您可以实现锁相环或线性回归或类似的东西,以更好地控制您的抖动,并避免由于网络滞后而导致的大幅摆动。该协议还规定了许多更复杂的特性,但如果您想实现它们,则取决于“足够好”的程度。

票数 6
EN

Stack Overflow用户

发布于 2011-05-19 06:11:11

ntp是适合这项工作的工具。你不需要互联网连接,只需多花105美元和几个小时的生活,你甚至可以在没有互联网连接的情况下获得绝对时间基准的GPS同步,尽管这对你来说似乎并不重要。

忽略GPS同步的略微增加的复杂性,您可以使用一些配置文件行(每个客户端四行,服务器五行)与所选系统的时钟同步。在我的系统上,ntpd二进制文件是505kB。您还可以使用ntpdate,它可以定期运行以调整系统时钟(客户端上的零行配置,而不是使用正确的参数调用ntpdate应用程序)。这个二进制文件是80kb。有一个SNTP协议,它允许嵌入式应用程序占用更小的空间(与正常的ntp服务器对话)。还有一种称为chrony的备用NTP实现。

还有一个叫做rdate的程序(通常只在旧系统上运行,虽然source是可用的),它的工作方式有点像ntpdate,但精确度要低得多。您还需要一个RFC 868服务器,通常在inetd中提供。

唯一的另一种选择是已经提到的精确时间协议。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5642946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档