NTP 客户端仅在干净编译后起作用

问题描述 投票:0回答:0

我正在尝试更好地学习 NTP 协议,但我在编写的一些测试代码中遇到了一个奇怪的问题,编译后第一对运行似乎运行良好,但之后无法返回值.我意识到这是一个游泳池,但它似乎可以立即工作或根本不工作。我认为我的内存管理不是问题,每次运行后我都运行 MD5sums 以确保我没有破坏二进制文件。如果我应该设置更多字段,我从稀疏文档中有点不清楚。有什么我应该设置的吗?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>

#define NTP_PORT 123
#define NTP_TIMESTAMP_DELTA 2208988800ull

// NTP packet structure
typedef struct {
    uint8_t li_vn_mode;           // LI (0-1), VN (2-4), Mode (5-7)
    uint8_t stratum;              // Stratum
    uint8_t poll;                 // Poll
    uint8_t precision;            // Precision
    uint32_t root_delay;          // Root Delay
    uint32_t root_dispersion;     // Root Dispersion
    uint32_t ref_id;              // Reference Identifier
    uint32_t ref_ts_sec;          // Reference Timestamp
    uint32_t ref_ts_frac;         // Reference Timestamp Fraction
    uint32_t orig_ts_sec;         // Origin Timestamp
    uint32_t orig_ts_frac;        // Origin Timestamp Fraction
    uint32_t rx_ts_sec; 
    uint32_t rx_ts_frac;
    uint32_t tx_ts_sec;
    uint32_t tx_ts_frac;
} ntp_packet;

// Create and send an NTP request to the specified server
int ntp_request(const char* server, ntp_packet* packet) {
    struct addrinfo hints, *res, *p;
    int status;
    char ipstr[INET6_ADDRSTRLEN];

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ((status = getaddrinfo(server, NULL, &hints, &res)) != 0)
    {
      fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
      return 2;
    }

     printf("IP address for %s:\n\n", server);
    for(p = res; p != NULL; p = p->ai_next)
    {
      void *addr;
      size_t sz = 5;
      char ipver[sz];
      if (p->ai_family == AF_INET)
      {
        struct sockaddr_in *ipv4 = (struct sockaddr_in *) p->ai_addr;
        addr = &(ipv4->sin_addr);
        memcpy(&ipver, "IPv4", sz);
      }
      else
      {
        struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
        addr = &(ipv6->sin6_addr);
        memcpy(&ipver, "IPv6", sz);
      }

      inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
      printf(" %s: %s\n", ipver, ipstr);
    }

    int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sockfd < 0) {
        perror("Failed to create socket");
        return -1;
    }

    // Set the NTP server address and port
    struct sockaddr_in servaddr;
    servaddr.sin_family = res->ai_family;
    servaddr.sin_port = htons(NTP_PORT);
    if (inet_aton(ipstr, &servaddr.sin_addr) == 0) {
        perror("Invalid server address");
        return -1;
    }

    // Send the NTP request
    memset(packet, 0, sizeof(ntp_packet));
    // NTP version 3, client mode, unauthenticated (00 011 011)
    packet->li_vn_mode = 0x1b;
    if (sendto(sockfd, packet, sizeof(ntp_packet), 0, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
        perror("Failed to send NTP request");
        return -1;
    }

    // Receive the NTP response
    memset(packet, 0, sizeof(ntp_packet));
    socklen_t addrlen = sizeof(servaddr);
    if (recvfrom(sockfd, packet, sizeof(ntp_packet), 0, (struct sockaddr*)&servaddr, &addrlen) < 0) {
        perror("Failed to receive NTP response");
        return -1;
    }

    freeaddrinfo(res);
    close(sockfd);
    return 0;
}

int main() {
    const char* server = "pool.ntp.org";
    ntp_packet packet;

    // Send an NTP request to the server
    if (ntp_request(server, &packet) < 0) {
        return -1;
    }

    // Process the NTP response and calculate the current time
    uint32_t ntp_timestamp = ntohl(packet.tx_ts_sec) - NTP_TIMESTAMP_DELTA;
    time_t current_time = (time_t)ntp_timestamp;

    printf("NTP server: %s\n", server);
    printf("NTP timestamp: %u\n", ntp_timestamp);
    printf("Current time: %s\n", ctime(&current_time));

    return 0;
}
c++ ntp
© www.soinside.com 2019 - 2024. All rights reserved.