Created
December 25, 2016 04:52
-
-
Save hirokuma/7d86ad644071026c697690da632e3300 to your computer and use it in GitHub Desktop.
sntp client(socket)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#define M_HOSTNAME_NTP "ntp.nict.jp" | |
#define M_LOCAL_PORT (123) | |
//https://www.ietf.org/rfc/rfc2030.txt | |
typedef struct { | |
uint8_t options; //b7-6:LI, b5-3:VN, b2-0:Mode | |
uint8_t stratum; | |
uint8_t poll; | |
uint8_t precision; | |
uint32_t root_delay; | |
uint32_t root_dispersion; | |
uint32_t ref_identifier; | |
uint32_t ref_timestamp[2]; | |
uint32_t orig_timestamp[2]; | |
uint32_t recv_timestamp[2]; | |
uint32_t trans_timestamp[2]; | |
//uint8_t key_identifier[4]; //optional | |
//uint8_t msg_digest[16]; //optional | |
} sntp_t; | |
int main(void) | |
{ | |
struct hostent *hostinfo; | |
ssize_t sz; | |
hostinfo = gethostbyname(M_HOSTNAME_NTP); | |
if (!hostinfo || (hostinfo->h_addrtype != AF_INET)) { | |
return; | |
} | |
int fd = socket(PF_INET, SOCK_DGRAM, 0); | |
if (fd == -1) { | |
printf("fail: sock\n"); | |
return; | |
} | |
struct sockaddr_in client_addr; | |
memset(&client_addr, 0, sizeof(client_addr)); | |
client_addr.sin_family = AF_INET; | |
client_addr.sin_addr.s_addr = INADDR_ANY; | |
client_addr.sin_port = htons(M_LOCAL_PORT); | |
if (bind(fd, (struct sockaddr *)&client_addr, sizeof(client_addr)) < 0) { | |
perror("fail: bind\n"); | |
return; | |
} | |
printf("bind ok\n"); | |
struct sockaddr_in server_addr; | |
memset(&server_addr, 0, sizeof(server_addr)); | |
server_addr.sin_family = AF_INET; | |
memcpy(&server_addr.sin_addr, hostinfo->h_addr, hostinfo->h_length); | |
server_addr.sin_port = htons(M_LOCAL_PORT); | |
printf("IP: %s(%d)\n", inet_ntoa(server_addr.sin_addr), M_LOCAL_PORT); | |
sntp_t sntp = {0}; | |
// LI=no warning(0), VN=4, Mode=client(3) | |
sntp.options = (0 << 6) | (4 << 3) | 3; | |
sz = sendto(fd, &sntp, sizeof(sntp), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); | |
printf("sendto=%d\n", (int)sz); | |
if (sz != sizeof(sntp)) { | |
perror("fail: sendto\n"); | |
return; | |
} | |
socklen_t len = sizeof(client_addr); | |
sz = recvfrom(fd, &sntp, sizeof(sntp), 0, (struct sockaddr *)&client_addr, &len); | |
printf("recvfrom=%d\n", (int)sz); | |
if (sz < 0) { | |
perror("fail: recvfrom\n"); | |
return; | |
} | |
uint32_t timestamp = htonl(sntp.trans_timestamp[0]) - 2208988800UL; | |
printf("ntp : %u\n", timestamp); | |
close(fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment