ntp实现原理
我们看一下为啥说ntp从实现时间同步的角度来说是很简单的。在pc上,以windows为例,手动关闭打开一下自动更新时间,会触发一次ntp时间同步。
这个时候,我们可以拿到ntp完整的request/response报文,如下:
ntp client request:
ntp server response:
如上图,我们可以看到,我们可以拿到同步原理提到的t1, t2, t3;而t4是client接收到server response时的时间,那么上述时间分别是如何来的呢。
* t1: client发送request的前一刻,记下当前utc时间,然后塞入到request transmit timestamp中去。但是这个不能作为真正的t1来使用,因为前面提到了,ntp是使用的udp,所以有可能会丢包。因此真正的t1应该ntp server收到client request时,从request报文中提取到t1,最后再给到client使用。也就是上图的t1。
* t2: 也就是server收到client request的时间
* t3: server发送response的时间
* t4: client收到server response的时间
知道这些原理之后,我们就可以很好设计出我们的代码实现思路,如下:
C++
//ntp client
// send request with t1
std::chrono::time_point_cast(
std::chrono::system_clock::now());
std::time_t time_stamp = time_point.time_since_epoch().count();
request_message_- >SetTransTs(time_stamp);
int ret = SendMsg(request_message_- >GetData(), MESSAGE_LENGTH);
// receive response, and get t1, t2, t3
int ret = RecvMsg(request_message_- >GetData(), MESSAGE_LENGTH);
auto req_tx_ts_ = response_message_- >GetOriginTs(); // t1
auto req_rx_ts_ = response_message_- >GetRecvTs(); // t2
auto resp_tx_ts_ = response_message_- >GetTransTs(); // t3
auto time_point = std::chrono::time_point_cast(
std::chrono::system_clock::now());
std::time_t time_stamp = time_point.time_since_epoch().count();
auto resp_rx_ts_us_ = static_cast(time_stamp); // t4
auto offset =
req_rx_ts_us_ - req_tx_ts_us_ + resp_tx_ts_us_ - resp_rx_ts_us_;
offset /= 2;
// adjust the clock
AdjustClock(offset);
C++
// ntp server
// receive ntp request message
RecvMsg(request_message_- >GetData(), MESSAGE_LENGTH);
// get receive request_frame timestamp, get t1, t2
auto time_point = std::chrono::time_point_cast(
std::chrono::system_clock::now());
auto req_rx_ts = time_point.time_since_epoch().count();//t2
auto req_tx_ts = request_message_- >GetTransTs();//t1
// send ntp response message
response_message_- >SetOriginTs(req_tx_ts);//t1
response_message_- >SetRecvTs(req_rx_ts);//t2
auto time_point = std::chrono::time_point_cast(
std::chrono::system_clock::now());
auto resp_tx_ts = time_point.time_since_epoch().count();
response_message_- >SetTransTs(resp_tx_ts);//t3
SendMsg(response_message_- >GetData(), MESSAGE_LENGTH);
全部0条评论
快来发表一下你的评论吧 !