没有NTP的小占用时钟同步

时间:2011-04-12 23:50:52

标签: networking synchronization ip distributed clock

我正在寻找一种简单的时钟同步协议,该协议易于实现,占用空间小,并且在没有互联网连接的情况下也可以使用,因此可以使用例如在封闭的实验室网络内为了清楚起见,我不是在寻找可以仅用于命令事件(如矢量时钟)的东西,而是能够使不同节点上的进程基于本地时钟同步其动作的东西。据我了解,这需要一个可以考虑时钟漂移的解决方案。可以假设存在TCP / IP或类似的相对低延迟的流连接。

6 个答案:

答案 0 :(得分:10)

免责声明:无论如何,我不是NTP专家。只是一个在周末玩乐的爱好者。

我意识到你说你不想要NTP实现,因为感知复杂性,并且因为你的环境中可能没有Internet NTP服务器。

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

以下是:

审核RFC 5905

您会看到NTP v4数据包类似于:

  • LI(2位)
  • VN(3位) - 使用'100'(4)
  • 模式(3位)
  • Stratum(8位)
  • 民意调查(8位)
  • 精确度(8位)
  • 根延迟(32位)
  • Root Dispersion(32位)
  • 参考ID(32位)
  • 参考时间戳(64位)
  • 原始时间戳(64位)
  • 接收时间戳(64位)
  • 传输时间戳(64位)
  • 扩展字段1(变量)
  • 扩展字段2(变量)
  • ...
  • 密钥标识符
  • 摘要(128位)

摘要不是必需的,因此形成有效的客户请求非常容易。遵循RFC中的指导,使用LI = '00',VN ='100'(小数4),Mode ='011'(小数3)。

使用C#来说明:

byte[] ntpData = new byte[48]
Array.Clear(ntpData, 0, ntpData.Length);
ntpData[0] = 0x23;  // LI = 00, VN = 100, Mode = 011

打开目标服务器的套接字并发送它。

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位。它表示自1月1日至1月1日0h以来的秒数。

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];

要使用(大致)第二粒度更新时钟,请使用:自1月1日1月1日起的秒数= intPart +(fractPart / 2 ^ 32)。 (我粗略地说,因为没有考虑网络延迟,我们在这里四舍五入)

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变得不那么透明。 =)

答案 1 :(得分:5)

我能够完全基于维基百科文章快速,轻松地实现精确时间协议的parred版本。如果您感兴趣的是将它们彼此同步而不是将它们与外部世界同步,那么您应该能够以最小的努力获得毫秒精度。

该协议的基本基础涉及以下内容:

  1. 主时钟广播同步消息,其中包含发送消息的时间戳(T1)。
  2. 客户端将收到同步消息的时间记录为T1'。
  3. 客户端向主服务器发送延迟请求,并将消息发送时间记录为T2。
  4. 主机在收到消息时响应延迟请求。这次是T2'。
  5. 客户端将时钟调整为(T1' - T1 - T2'+ T2)/ 2.
  6. 如果你需要更好的稳定性,你可以实现一个锁相环或线性回归或类似的东西,以更好地控制你的抖动,并避免由于网络滞后造成的大幅波动。协议指定了许多更复杂的功能,但是如果要实现它们取决于“足够好”的接近程度。

答案 2 :(得分:2)

可能Precision Time Protocol适合这个账单吗?它看起来并不简单,但似乎或多或少地完全符合您的要求。 (维基百科页面上引用了一些开源实现。)

我认为问题在于这是一个固有的棘手问题,因此解决方案往往很复杂。 NTP正试图提供一个正确的绝对时间,这绝对超出了你的需要,但它确实具有众所周知和广泛实施的优势。

答案 3 :(得分:2)

ntp是这项工作的正确工具。您不需要互联网连接,并且额外花费105美元和几个小时的生活,您甚至可以在没有互联网连接的情况下进行GPS同步以获得绝对时间参考,但这似乎对您来说并不重要。

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

还有一个名为rdate的程序(通常仅在较旧的系统上,虽然source可用),它的工作方式类似于ntpdate,但更不精确。您还需要一个RFC 868服务器,通常在inetd中提供。

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

答案 4 :(得分:0)

使用http://www.ietf.org/rfc/rfc5905.txt可能合适吗?

即使它比您需要的多得多,您当然可以实现与NTP服务器一起使用的“兼容”客户端(即使您运行自己的NTP服务器),但客户端实现是故意天真的?< / p>

例如,如果您不关心小时间调整,请不要实施它们。如果您不关心双向同步,请不要实现,等等。

(请注意:RFC中存在的大多数功能都有一个原因 - 准确的时间同步存在许多缺陷 - 包括如果时间突然改变,许多操作系统不喜欢它的事实)

答案 5 :(得分:0)

不是一个正确的答案,但只是提醒您确保您确切了解硬件时钟源是什么以及有关它们的任何警告 - 特别是如果您计划使用一些略有异国情调的可能性,如低功耗CPU /您提到的RTOS组合。

即使x86机箱至少有2或3个时钟可以使用,具体取决于设置 - 所有时钟都具有不同的属性。