记录工作实践:IEC61850协议通信过程中,需要通过SNTP协议进行对时功能,为验证此功能所以在windows11平台上面搭建NTP服务器,在开发板上面运行对时程序从而实现对时功能。
windows11搭建SNTP服务步骤:经查询Windows系统本身是可以作NTP时间同步服务器的,无需安装其它软件,只需要修改一些配置。
1.修改注册表:使用win + R 组合键在运行窗口中输入regedit,打开注册表编辑器。
2.修改以下注册表内容:
计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer,把Enabled设置为1
计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config,并把AnnounceFlags的值设置为5(系统默认为a)
3.启动NTP服务:通过管理员身份运行CMD命令行,依次输入命令
输入net stop w32time 输出以下信息表示没有打开NTP服务
输入net start w32time
启动服务,下图表示启动成功
4.本地测试
在cmd窗口中输入w32tm /stripchart /computer:192.168.1.100 ,如果有回显则服务正常。
以上表示为NTP服务搭建成功。
NTP服务功能测试:测试程序如下
1.sntp.c
#include "sntp.h"struct s_fixedpt { uint16_t intpart; uint16_t fracpart;}; struct l_fixedpt { uint32_t intpart; uint32_t fracpart;}; struct ntphdr {#if __BYTE_ORDER == __BID_ENDIAN unsigned int ntp_li : 2; unsigned int ntp_vn : 3; unsigned int ntp_mode : 3;#endif#if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int ntp_mode : 3; unsigned int ntp_vn : 3; unsigned int ntp_li : 2;#endif uint8_t ntp_stratum; uint8_t ntp_poll; int8_t ntp_precision; struct s_fixedpt ntp_rtdelay; struct s_fixedpt ntp_rtdispersion; uint32_t ntp_refid; struct l_fixedpt ntp_refts; struct l_fixedpt ntp_orits; struct l_fixedpt ntp_recvts; struct l_fixedpt ntp_transts;}; in_addr_t inet_host(const char* host){ in_addr_t saddr; struct hostent* hostent; if ((saddr = inet_addr(host)) == INADDR_NONE) { if ((hostent = gethostbyname(host)) == NULL) return INADDR_NONE; memmove(&saddr, hostent->h_addr, hostent->h_length); } return saddr;} int get_ntp_packet(void* buf, size_t* size){ struct ntphdr* ntp; struct timeval tv; if (!size || *size < NTP_HLEN) return -1; memset(buf, 0, *size); ntp = (struct ntphdr*)buf; ntp->ntp_li = NTP_LI; ntp->ntp_vn = NTP_VN; ntp->ntp_mode = NTP_MODE; ntp->ntp_stratum = NTP_STRATUM; ntp->ntp_poll = NTP_POLL; ntp->ntp_precision = NTP_PRECISION; gettimeofday(&tv, NULL); ntp->ntp_transts.intpart = htonl(tv.tv_sec + JAN_1970); ntp->ntp_transts.fracpart = htonl(USEC2FRAC(tv.tv_usec)); *size = NTP_HLEN; return 0;} void print_ntp(struct ntphdr* ntp){ time_t time; printf("LI:\t%d \n", ntp->ntp_li); printf("VN:\t%d \n", ntp->ntp_vn); printf("Mode:\t%d \n", ntp->ntp_mode); printf("Stratum:\t%d \n", ntp->ntp_stratum); printf("Poll:\t%d \n", ntp->ntp_poll); printf("precision:\t%d \n", ntp->ntp_precision); printf("Route delay:\t %lf \n", ntohs(ntp->ntp_rtdelay.intpart) + NTP_REVE_FRAC16(ntohs(ntp->ntp_rtdelay.fracpart))); printf("Route Dispersion:\t%lf \n", ntohs(ntp->ntp_rtdispersion.intpart) + NTP_REVE_FRAC16(ntohs(ntp->ntp_rtdispersion.fracpart))); printf("Referencd ID:\t %d \n", ntohl(ntp->ntp_refid)); time = ntohl(ntp->ntp_refts.intpart) - JAN_1970; printf("Reference:\t%d %ld %s \n", ntohl(ntp->ntp_refts.intpart) - JAN_1970, FRAC2USEC(ntohl(ntp->ntp_refts.fracpart)), ctime(&time)); time = ntohl(ntp->ntp_orits.intpart) - JAN_1970; printf("Originate:\t%d %d frac=%ld (%s) \n", ntohl(ntp->ntp_orits.intpart) - JAN_1970, FRAC2USEC(ntohl(ntp->ntp_orits.fracpart)), ntohl(ntp->ntp_orits.fracpart), ctime(&time)); time = ntohl(ntp->ntp_recvts.intpart) - JAN_1970; printf("Receive:\t%d %d (%s) \n", ntohl(ntp->ntp_recvts.intpart) - JAN_1970, FRAC2USEC(ntohl(ntp->ntp_recvts.fracpart)), ctime(&time)); time = ntohl(ntp->ntp_transts.intpart) - JAN_1970; printf("Transmit:\t%d %d (%s) \n", ntohl(ntp->ntp_transts.intpart) - JAN_1970, FRAC2USEC(ntohl(ntp->ntp_transts.fracpart)), ctime(&time));} double get_rrt(const struct ntphdr* ntp, const struct timeval* recvtv){ double t1, t2, t3, t4; t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits); t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts); t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts); t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0; return (t4 - t1) - (t3 - t2);} double get_offset(const struct ntphdr* ntp, const struct timeval* recvtv){ double t1, t2, t3, t4; t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits); t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts); t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts); t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0; return ((t2 - t1) + (t3 - t4)) / 2;} void usage(void){ fprintf(stderr, "Usage : ntpclient" " destination" "\n" );} int main(){ char buf[BUFSIZE]; size_t nbytes; int sockfd, maxfd1; struct sockaddr_in servaddr; fd_set readfds; struct timeval timeout, recvtv, tv; double offset; servaddr.sin_family = AF_INET; servaddr.sin_port = htons(NTP_PORT); servaddr.sin_addr.s_addr = inet_host(NTP_SERVER); if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket error"); exit(-1); } if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)) != 0) { perror("connect error"); exit(-1); } nbytes = BUFSIZE; if (get_ntp_packet(buf, &nbytes) != 0) { fprintf(stderr, "construct ntp request error \n"); exit(-1); } send(sockfd, buf, nbytes, 0); FD_ZERO(&readfds); FD_SET(sockfd, &readfds); maxfd1 = sockfd + 1; timeout.tv_sec = TIMEOUT; timeout.tv_usec = 0; if (select(maxfd1, &readfds, NULL, NULL, &timeout) > 0) { if (FD_ISSET(sockfd, &readfds)) { if ((nbytes = recv(sockfd, buf, BUFSIZE, 0)) < 0) { perror("recv error"); exit(-1); } //计算客户端时间与服务器端时间偏移量 gettimeofday(&recvtv, NULL); offset = get_offset((struct ntphdr*)buf, &recvtv); //更新系统时间 gettimeofday(&tv, NULL); tv.tv_sec += (int)offset; tv.tv_usec += offset - (int)offset; if (settimeofday(&tv, NULL) != 0) { perror("settimeofday error"); exit(-1); } /*printf("time=%s\n", ctime((time_t*)&tv.tv_sec)); char time_string[80]; strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", localtime(&tv.tv_sec)); printf("date -s %s\n", time_string);*/ } } close(sockfd); return 0;}
sntp.h
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <sys/select.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netdb.h>#include <errno.h>#include <endian.h> #define VERSION_3 3#define VERSION_4 4#define MODE_CLIENT 3#define MODE_SERVER 4#define NTP_LI 0#define NTP_VN VERSION_3 #define NTP_MODE MODE_CLIENT#define NTP_STRATUM 0#define NTP_POLL 4#define NTP_PRECISION -6#define NTP_HLEN 48#define NTP_PORT 123#define NTP_SERVER "192.168.1.100"#define TIMEOUT 10#define BUFSIZE 1500#define JAN_1970 0x83aa7e80#define NTP_CONV_FRAC32(x) (uint64_t) ((x) * ((uint64_t)1<<32)) #define NTP_REVE_FRAC32(x) ((double) ((double) (x) / ((uint64_t)1<<32))) #define NTP_CONV_FRAC16(x) (uint32_t) ((x) * ((uint32_t)1<<16)) #define NTP_REVE_FRAC16(x) ((double)((double) (x) / ((uint32_t)1<<16))) #define USEC2FRAC(x) ((uint32_t) NTP_CONV_FRAC32( (x) / 1000000.0 )) #define FRAC2USEC(x) ((uint32_t) NTP_REVE_FRAC32( (x) * 1000000.0 )) #define NTP_LFIXED2DOUBLE(x) ((double) ( ntohl(((struct l_fixedpt *) (x))->intpart) - JAN_1970 + FRAC2USEC(ntohl(((struct l_fixedpt *) (x))->fracpart)) / 1000000.0 ))
2.通过交叉编译工具生成可执行程序。aarch64-linux-gnu-gcc ntp_time.c -o ntp -lpthread 交叉编译工具需与编译平台保持一致。
以下为输出结果。
原网址: 访问
创建于: 2024-06-14 15:16:31
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论