Skip to content

Instantly share code, notes, and snippets.

@hirokuma
Created December 25, 2016 04:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hirokuma/7d86ad644071026c697690da632e3300 to your computer and use it in GitHub Desktop.
Save hirokuma/7d86ad644071026c697690da632e3300 to your computer and use it in GitHub Desktop.
sntp client(socket)
#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