用c语言写一个ntp服务端的代码
时间: 2024-05-07 10:23:17 浏览: 110
以下是一个简单的NTP服务端的C语言代码示例:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define NTP_TIMESTAMP_DELTA 2208988800ull
#define NTP_PACKET_SIZE 48
int main() {
int sockfd;
struct sockaddr_in servaddr;
uint8_t packet[NTP_PACKET_SIZE];
memset(packet, 0, sizeof(packet));
packet[0] = 0x1b;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
perror("socket");
exit(1);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(123);
if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
perror("bind");
exit(1);
}
while (1) {
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
ssize_t n = recvfrom(sockfd, packet, sizeof(packet), 0, (struct sockaddr*)&cliaddr, &len);
if (n < 0) {
perror("recvfrom");
continue;
}
if (n != NTP_PACKET_SIZE) {
printf("Invalid NTP packet size %ld\n", n);
continue;
}
uint32_t secs = ntohl(*((uint32_t*)&packet[40]));
uint32_t frac = ntohl(*((uint32_t*)&packet[44]));
printf("Received NTP request from %s\n", inet_ntoa(cliaddr.sin_addr));
printf("Unix time: %u.%u\n", secs - NTP_TIMESTAMP_DELTA, frac);
time_t t = time(NULL);
uint32_t curr_secs = (uint32_t)t + NTP_TIMESTAMP_DELTA;
uint32_t curr_frac = (uint32_t)(((double)(t - (time_t)curr_secs) / 1.0e9) * (1LL<<32));
memset(packet, 0, sizeof(packet));
packet[0] = 0x1c;
*((uint32_t*)&packet[40]) = htonl(curr_secs);
*((uint32_t*)&packet[44]) = htonl(curr_frac);
n = sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr*)&cliaddr, len);
if (n < 0) {
perror("sendto");
continue;
}
}
return 0;
}
```
该代码创建了一个UDP套接字并将其绑定到本地主机上的UDP端口123。它接收来自客户端的NTP请求,解析请求中的时间戳,并向客户端发送一个响应,其中包含当前时间戳。请注意,这是一个非常简单的示例,没有进行任何错误检查或安全性检查。在实际使用中,请务必加以改进。
阅读全文