首页 > 解决方案 > ntp 服务器丢包。怎么解决?选择不工作

问题描述

出于某种原因,我不知道有时我的设备没有收到来自 ntp 服务器的答复,而是卡在了读取套接字中。我尝试使用选择来解决这个问题。但我总是超时。使用 select 有什么问题?它总是返回 0 而不是字节数

int ntp_get_time(char *host_name) {

int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket.

int portno = 123; // NTP UDP port number.
// Structure that defines the 48 byte NTP packet protocol.


// Create and zero out the packet. All 48 bytes worth.

ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

memset(&packet, 0, sizeof(ntp_packet));

// Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero.

*((char *) &packet + 0) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2.

// Create a UDP socket, convert the host-name to an IP address, set the port number,
// connect to the server, send the packet, and then read in the return packet.

struct sockaddr_in serv_addr; // Server address data structure.
struct hostent *server;      // Server data structure.

sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Create a UDP socket.

if (sockfd < 0) {
    dlog_print(DLOG_ERROR, LOG_TAG, "ERROR opening socket");
    if (sockfd)
        close(sockfd); // [joao]
    return -1;
}
dlog_print(DLOG_INFO, LOG_TAG, "host_name: %s", host_name);
server = gethostbyname(host_name); // Convert URL to IP.

if (server == NULL) {
    dlog_print(DLOG_ERROR, LOG_TAG, "ERROR, no such host");
    if (sockfd)
        close(sockfd); // [joao]
    return -1;
}

// Zero out the server address structure.

bzero((char*) &serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;

// Copy the server's IP address to the server address structure.

bcopy((char*) server->h_addr, ( char* ) &serv_addr.sin_addr.s_addr, server->h_length );

// Convert the port number integer to network big-endian style and save it to the server address structure.

serv_addr.sin_port = htons(portno);

// Call up the server using its IP address and port number.

if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
        < 0) {
    dlog_print(DLOG_ERROR, LOG_TAG, "ERROR connecting");
    if (sockfd)
        close(sockfd); // [joao]
    return -1;
}
else {
    dlog_print(DLOG_INFO, LOG_TAG, "conect sockect success");
}

struct timeval t0;
int res = 0;
res = gettimeofday(&t0, NULL);
dlog_print(DLOG_INFO, LOG_TAG, "gettimeofday res = %d", res);

// Send it the NTP packet it wants. If n == -1, it failed.
n = write(sockfd, (char*) &packet, sizeof(ntp_packet));

if (n < 0) {
    dlog_print(DLOG_ERROR, LOG_TAG, "ERROR writing to socket");
    if (sockfd)
        close(sockfd); // [joao]
    return -1;
}
else {
    dlog_print(DLOG_INFO, LOG_TAG, "write sockect success");
}

// Wait and receive the packet back from the server. If n == -1, it failed.
fd_set rfds;
struct timeval timeout;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
/* Wait up to five seconds. */
timeout.tv_sec = 2;
timeout.tv_usec = 0;

retval = select(1, &rfds, NULL, NULL, &timeout);
/* Don't rely on the value of tv now! */

if (retval == -1) {
     dlog_print(DLOG_INFO, LOG_TAG, "error in select =%d", retval);
    return retval;
}
else if (retval) {
    n = read(sockfd, (char*) &packet, sizeof(ntp_packet));
    dlog_print(DLOG_INFO, LOG_TAG, "read sockfd n =%d", n);
}
else {
    dlog_print(DLOG_INFO, LOG_TAG, "No data within 2 seconds retval =%d", retval);
    return retval;
}

标签: csockets

解决方案


推荐阅读