NTP 实现 C
NTP implementation C
有人能找到我在 ntp 实施中遗漏的内容吗?
我正在为 32 位微控制器 ARM Cortex M3 编程。
我有三个函数 - wifiSend,它调用 bsdUdpClient 和 bsdUdpServer。 bsdUdpClient向服务器发送数据,bsdUdpServer监听保留的NTP端口,接收NTP服务器的数据。
我没有收到任何错误消息,但收到的缓冲区是空的。
static void wifiSend(xTimerHandle xTimer){
uint16_t AddrSize = sizeof(SlSockAddrIn_t);
if (STATUS_OK != bsdUdpClient(SERVER_PORT, AddrSize)){
printf("Failed to send udp packet\n\r");
assert(false);
}
if (STATUS_OK != bsdUdpServer(SERVER_PORT, AddrSize))
printf("Failed to receive udp packet\n\r");
}
static returnTypes_t bsdUdpClient(uint16_t port, uint16_t AddrSize){
int16_t Status = (int16_t) ZERO;
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode
packetBuffer[1] = 0x00; // Stratum, or type of clock
packetBuffer[2] = 0x06; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Addr.sin_family = SL_AF_INET;
Addr.sin_port = sl_Htons((uint16_t) port);
Addr.sin_addr.s_addr = sl_Htonl(SERVER_IP);
SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
if (SockID < (int16_t) ZERO)
return (SOCKET_ERROR);
Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);
if (Status <= (int16_t) ZERO) {
Status = sl_Close(SockID);
if (Status < 0)
return (SEND_ERROR);
return (SEND_ERROR);
}
Status = sl_Close(SockID);
if (Status < 0)
return (SEND_ERROR);
return (STATUS_OK);
}
static returnTypes_t bsdUdpServer(uint16_t port, uint16_t AddrSize){
int16_t Status = (int16_t) ZERO;
LocalAddr.sin_family = SL_AF_INET;
LocalAddr.sin_port = sl_Htons(5001);
LocalAddr.sin_addr.s_addr = 0;
SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, (uint32_t) ZERO);
if (SockID < 0){
printf("error on sl_Socket\n\r");
return SOCKET_ERROR;
}
Status = sl_Bind(SockID, (SlSockAddr_t *) &LocalAddr, AddrSize);
if (Status < 0){
printf("problem on sl_Bind\n\r");
return SOCKET_ERROR;
}
Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
if (Status < (int16_t) ZERO){
printf("error - no bytes received: %d\n\r", (int16_t)Status);
return SOCKET_ERROR;
}
Status = sl_Close(SockID);
if (Status < 0)
printf("problem on sl_Close\n\r");
uint8_t index3 = packetBuffer[40];
uint8_t index2 = packetBuffer[41];
uint8_t index1 = packetBuffer[42];
uint8_t index0 = packetBuffer[43];
uint16_t highWord = index3 << 16 | index2;
uint16_t lowWord = index1 << 16 | index0;
uint32_t secondsSince1900 = highWord << 16 | lowWord;
printf("Seconds since 1 Janeiro de 1900: %ld\n\r", secondsSince1900);
return (STATUS_OK);
}
您的客户端代码发送了一个查询,但随后关闭了套接字并且从不监听回复。
您的服务器代码等待查询,但从不发送任何响应。
它们似乎都没有做任何特别有用的事情。您应该完成客户端代码,以便它在关闭套接字之前侦听回复。请注意,您应该使用超时,这样您就不会在查询或响应丢失的情况下永远等待。
感谢@DavidSchwartz,我现在有了一个可行的解决方案。
我还修复了一个错误,当时我试图从收到的数据包中提取自 1900 年 1 月 1 日以来的秒数。
希望对大家有所帮助。
待改进:添加超时以避免服务器无响应时的阻塞状态
#define NTP_PACKET_SIZE 48
uint8_t packetBuffer[ NTP_PACKET_SIZE];
static returnTypes_t bsdUdpClient(uint16_t AddrSize){
int16_t Status = (int16_t) ZERO;
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode
packetBuffer[1] = 0x00; // Stratum, or type of clock
packetBuffer[2] = 0x06; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
if (SockID < (int16_t) ZERO)
return (SOCKET_ERROR);
/*make the request to the server*/
Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);
/*Check if 0 transmitted bytes sent or error condition*/
if (Status <= (int16_t) ZERO) {
sl_Close(SockID);
return (SEND_ERROR);
}
else
printf("request sent successfully\n\r");
/* receive the reply from the server*/
Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
if (Status < (int16_t) ZERO){
printf("error - no bytes received: %d\n\r", (int16_t)Status);
return SOCKET_ERROR;
}
else
printf("reply received\n\r");
Status = sl_Close(SockID);
if (Status < 0)
printf("problem on sl_Close\n\r");
uint8_t index3 = packetBuffer[40];
uint8_t index2 = packetBuffer[41];
uint8_t index1 = packetBuffer[42];
uint8_t index0 = packetBuffer[43];
uint16_t highWord = index3 << 8 | index2;
uint16_t lowWord = index1 << 8 | index0;
uint32_t secondsSince1900 = highWord << 16 | lowWord;
printf("Seconds since 1 Janeiro de 1900: %lu\n\r", secondsSince1900);
return (STATUS_OK);
}
有人能找到我在 ntp 实施中遗漏的内容吗?
我正在为 32 位微控制器 ARM Cortex M3 编程。 我有三个函数 - wifiSend,它调用 bsdUdpClient 和 bsdUdpServer。 bsdUdpClient向服务器发送数据,bsdUdpServer监听保留的NTP端口,接收NTP服务器的数据。
我没有收到任何错误消息,但收到的缓冲区是空的。
static void wifiSend(xTimerHandle xTimer){
uint16_t AddrSize = sizeof(SlSockAddrIn_t);
if (STATUS_OK != bsdUdpClient(SERVER_PORT, AddrSize)){
printf("Failed to send udp packet\n\r");
assert(false);
}
if (STATUS_OK != bsdUdpServer(SERVER_PORT, AddrSize))
printf("Failed to receive udp packet\n\r");
}
static returnTypes_t bsdUdpClient(uint16_t port, uint16_t AddrSize){
int16_t Status = (int16_t) ZERO;
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode
packetBuffer[1] = 0x00; // Stratum, or type of clock
packetBuffer[2] = 0x06; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Addr.sin_family = SL_AF_INET;
Addr.sin_port = sl_Htons((uint16_t) port);
Addr.sin_addr.s_addr = sl_Htonl(SERVER_IP);
SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
if (SockID < (int16_t) ZERO)
return (SOCKET_ERROR);
Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);
if (Status <= (int16_t) ZERO) {
Status = sl_Close(SockID);
if (Status < 0)
return (SEND_ERROR);
return (SEND_ERROR);
}
Status = sl_Close(SockID);
if (Status < 0)
return (SEND_ERROR);
return (STATUS_OK);
}
static returnTypes_t bsdUdpServer(uint16_t port, uint16_t AddrSize){
int16_t Status = (int16_t) ZERO;
LocalAddr.sin_family = SL_AF_INET;
LocalAddr.sin_port = sl_Htons(5001);
LocalAddr.sin_addr.s_addr = 0;
SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, (uint32_t) ZERO);
if (SockID < 0){
printf("error on sl_Socket\n\r");
return SOCKET_ERROR;
}
Status = sl_Bind(SockID, (SlSockAddr_t *) &LocalAddr, AddrSize);
if (Status < 0){
printf("problem on sl_Bind\n\r");
return SOCKET_ERROR;
}
Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
if (Status < (int16_t) ZERO){
printf("error - no bytes received: %d\n\r", (int16_t)Status);
return SOCKET_ERROR;
}
Status = sl_Close(SockID);
if (Status < 0)
printf("problem on sl_Close\n\r");
uint8_t index3 = packetBuffer[40];
uint8_t index2 = packetBuffer[41];
uint8_t index1 = packetBuffer[42];
uint8_t index0 = packetBuffer[43];
uint16_t highWord = index3 << 16 | index2;
uint16_t lowWord = index1 << 16 | index0;
uint32_t secondsSince1900 = highWord << 16 | lowWord;
printf("Seconds since 1 Janeiro de 1900: %ld\n\r", secondsSince1900);
return (STATUS_OK);
}
您的客户端代码发送了一个查询,但随后关闭了套接字并且从不监听回复。
您的服务器代码等待查询,但从不发送任何响应。
它们似乎都没有做任何特别有用的事情。您应该完成客户端代码,以便它在关闭套接字之前侦听回复。请注意,您应该使用超时,这样您就不会在查询或响应丢失的情况下永远等待。
感谢@DavidSchwartz,我现在有了一个可行的解决方案。
我还修复了一个错误,当时我试图从收到的数据包中提取自 1900 年 1 月 1 日以来的秒数。
希望对大家有所帮助。
待改进:添加超时以避免服务器无响应时的阻塞状态
#define NTP_PACKET_SIZE 48
uint8_t packetBuffer[ NTP_PACKET_SIZE];
static returnTypes_t bsdUdpClient(uint16_t AddrSize){
int16_t Status = (int16_t) ZERO;
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode
packetBuffer[1] = 0x00; // Stratum, or type of clock
packetBuffer[2] = 0x06; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
if (SockID < (int16_t) ZERO)
return (SOCKET_ERROR);
/*make the request to the server*/
Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);
/*Check if 0 transmitted bytes sent or error condition*/
if (Status <= (int16_t) ZERO) {
sl_Close(SockID);
return (SEND_ERROR);
}
else
printf("request sent successfully\n\r");
/* receive the reply from the server*/
Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
if (Status < (int16_t) ZERO){
printf("error - no bytes received: %d\n\r", (int16_t)Status);
return SOCKET_ERROR;
}
else
printf("reply received\n\r");
Status = sl_Close(SockID);
if (Status < 0)
printf("problem on sl_Close\n\r");
uint8_t index3 = packetBuffer[40];
uint8_t index2 = packetBuffer[41];
uint8_t index1 = packetBuffer[42];
uint8_t index0 = packetBuffer[43];
uint16_t highWord = index3 << 8 | index2;
uint16_t lowWord = index1 << 8 | index0;
uint32_t secondsSince1900 = highWord << 16 | lowWord;
printf("Seconds since 1 Janeiro de 1900: %lu\n\r", secondsSince1900);
return (STATUS_OK);
}