网络时间协议NTP工作模式

单播服务器/客户端模式

单播服务器/客户端模式运行在同步子网中层数较高层上。这种模式下,需要预先知道服务器的IP地址。
客户端:运行在客户端模式的主机(简称客户端)定期向服务器端发送报文,报文中的Mode字段设置为3(客户端模式)。当客户端接收到应答报文时,客户端会进行时钟过滤和选择,并同步到时钟优选的服务器。客户端不管服务器端是否可达及服务器端的层数。运行在这种模式的主机,通常是网络内部的工作站,它可以依照对方的时钟进行同步,但不会修改对方的时钟。
服务器:运行在服务器模式(简称服务器)的主机接收并回应报文,报文中的Mode字段设置为4(服务器模式)。运行在服务器模式的主机,通常是网络内部的时间服务器,它可以向客户端提供同步信息,但不会修改自己的时钟。
在这里插入图片描述
运行在客户端模式的主机在重新启动时和重新启动后定期向运行在服务器模式的主机发送NTP报文。服务器收到客户端的报文后,首先将报文的目的IP地址和目的端口号分别与其源IP地址和源端口号相交换,再填写所需的信息,然后把报文发送给客户端。服务器无需保留任何状态信息,客户端根据本地情况自由管理发送报文的时间间隔。

对等体模式

对等体模式运行在同步子网中层数较低处。这种模式下,主动对等体和被动对等体可以互相同步,等级低(层数大)的对等体向等级高(层数小)的对等体同步。
对等体模式下,主动

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用 C/C++ 中的网络编程库(如 socket)与 NTP 服务器进行通信,获取网络时间戳。具体步骤如下: 1. 创建一个 UDP 套接字; 2. 连接 NTP 服务器的 IP 地址和端口号(一般为 123); 3. 构造 NTP 请求报文(如下图所示): ``` ┌─────────────────┬─────────────────┬───────────────────┬───────────────┐ │ LI │ VN │ Mode │ Stratum │ │ 2 bits │ 3 bits │ 3 bits │ 8 bits │ ├─────────────────┼─────────────────┼───────────────────┼───────────────┤ │ Poll │ Precision │ Root Delay │ Root Dispersion│ │ 8 bits │ 8 bits │ 16 bits │ 16 bits │ ├─────────────────┼─────────────────┼───────────────────┼───────────────┤ │ Reference ID │ │ 32 bits │ ├─────────────────┼─────────────────┼───────────────────┼───────────────┤ │ Reference Timestamp (64 bits) │ ├─────────────────┼─────────────────┼───────────────────┼───────────────┤ │ Origin Timestamp (64 bits) │ ├─────────────────┼─────────────────┼───────────────────┼───────────────┤ │ Receive Timestamp (64 bits) │ ├─────────────────┼─────────────────┼───────────────────┼───────────────┤ │ Transmit Timestamp (64 bits) │ └─────────────────┴─────────────────┴───────────────────┴───────────────┘ ``` 其中,各字段含义如下: - LI: 协议版本号(2 bits); - VN: NTP 版本号(3 bits); - Mode: 模式(3 bits),用于指示 NTP 报文类型; - Stratum: 层级(8 bits),表示距离时钟源(如原子钟)的层级; - Poll: 轮询间隔(8 bits),表示发送 NTP 请求报文的时间间隔; - Precision: 精度(8 bits),表示本地时钟的精度; - Root Delay: 根时钟延迟(16 bits),表示距离时钟源的延迟; - Root Dispersion: 根时钟离散度(16 bits),表示距离时钟源的离散度; - Reference ID: 参考时钟源 ID(32 bits),用于指示参考时钟源; - Reference Timestamp: 参考时间戳(64 bits),表示参考时钟源的时间戳; - Origin Timestamp: 发起请求的时间戳(64 bits); - Receive Timestamp: 接收到请求的时间戳(64 bits); - Transmit Timestamp: 发送响应的时间戳(64 bits)。 4. 发送 NTP 请求报文到 NTP 服务器; 5. 接收 NTP 响应报文,并解析其中的 Transmit Timestamp 字段,即可得到网络时间戳。 以下是一个简单的 C++ 实现示例: ```cpp #include <iostream> #include <string> #include <cstring> #include <ctime> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> using namespace std; #define NTP_SERVER "pool.ntp.org" #define NTP_PORT 123 #define NTP_PACKET_SIZE 48 // NTP 时间戳的起始时间(1900 年 1 月 1 日) const time_t NTP_TIMESTAMP_DELTA = 2208988800; // 构造 NTP 请求报文 void build_ntp_packet(char* packet) { memset(packet, 0, NTP_PACKET_SIZE); packet[0] = 0b11100011; // LI, VN, Mode packet[1] = 0; // Stratum packet[2] = 6; // Poll packet[3] = 0xEC; // Precision // Root Delay & Root Dispersion packet[12] = 49; packet[13] = 0x4E; packet[14] = 49; packet[15] = 52; } // 从 NTP 响应报文中解析时间戳 time_t parse_ntp_packet(const char* packet) { uint32_t timestamp = ntohl((uint32_t&)packet[40]); return timestamp - NTP_TIMESTAMP_DELTA; } int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockfd == -1) { cerr << "Failed to create socket" << endl; return -1; } struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(NTP_PORT); if (inet_pton(AF_INET, NTP_SERVER, &server_addr.sin_addr) == -1) { cerr << "Invalid server address" << endl; return -1; } char packet[NTP_PACKET_SIZE]; build_ntp_packet(packet); if (sendto(sockfd, packet, NTP_PACKET_SIZE, 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { cerr << "Failed to send NTP request" << endl; return -1; } char response[NTP_PACKET_SIZE]; socklen_t addrlen = sizeof(server_addr); if (recvfrom(sockfd, response, NTP_PACKET_SIZE, 0, (struct sockaddr*)&server_addr, &addrlen) == -1) { cerr << "Failed to receive NTP response" << endl; return -1; } time_t timestamp = parse_ntp_packet(response); cout << "Network timestamp: " << ctime(&timestamp) << endl; close(sockfd); return 0; } ``` 注意,此实现仅用于演示目的,实际生产环境中需要考虑更多的异常情况和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_Puter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值