无NTP的小占用时钟同步 [英] Small footprint clock synchronization without NTP

查看:159
本文介绍了无NTP的小占用时钟同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

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



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



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

以下是:



评论 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);

在响应中,当前时间将在Transmit Timestamp中(字节[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日0时起的秒数-1900 = 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变得不那么透明。 =)


I'm looking for a simple clock synchronization protocol that would be easy to implement with small footprint and that would work also in the absence of internet connection, so that it could be used e.g. within closed laboratory networks. To be clear, I'm not looking for something that can be used just to order events (like vector clocks), but something that would enable processes on different nodes to synchronize their actions based on local clocks. As far as I understand, this would require a solution that can take clock drift into account. Presence of TCP/IP or similar relatively low-latency stream connections can be assumed.

解决方案

Disclaimer: I'm not an NTP expert by any means. Just a hobbyist having fun on the weekend.

I realize you said you didn't want an NTP implementation, because of the perceived complexity and because an Internet NTP server may not be available in your environment.

However, an simplified NTP look-up may be easy to implement, and if you have a local NTP server you can achieve good synchronization.

Here's how:

Review RFC 5905

You'll see NTP v4 packets look something like:

  • LI (2 bits)
  • VN (3 bits) - Use '100' (4)
  • Mode (3 bits)
  • Stratum (8 bits)
  • Poll (8 bits)
  • Precision (8 bits)
  • Root Delay (32 bits)
  • Root Dispersion (32 bits)
  • Reference Id (32 bits)
  • Reference Timestamp (64 bits)
  • Origin Timestamp (64 bits)
  • Receive Timestamp (64 bits)
  • Transmit Timestamp (64 bits)
  • Extension Field 1 (variable)
  • Extension Field 2 (variable)
  • ...
  • Key Identifier
  • Digest (128 bits)

The digest is not required, so forming a valid client request is very easy. Following the guidance in the RFC, use LI = '00', VN = '100' (decimal 4), Mode = '011' (decimal 3).

Using C# to illustrate:

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

Open a socket to your target server and send it over.

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

In the response, the current time will be in the Transmit Timestamp (bytes [40 - 48]). Timestamps are 64-bit unsigned fixed-point numbers. The integer part is the first 32 bits, the fractional part is the last 32 bits. It represents the number of seconds since 0h on Jan-1-1900.

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

To update the clock with (roughly) second granularity, use: # of seconds since 0h Jan-1-1900 = intPart + (fractPart / 2^32). (I say roughly because network latency isn't accounted for, and we're rounding down here)

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" is now a DateTime with the current time, in UTC.

While this might not answer your question, hopefully it makes NTP a little less opaque. =)

这篇关于无NTP的小占用时钟同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆