WT与RTC
网上自行搜索了解两者区别:
-
系统时间(WT, Wall Time):由Linux系统软件维持的时间。
-
RTC(Real-Time Clock):翻译过来是实时时钟芯片。
对于一台安装了操作系统的服务器来说,操作系统和服务器硬件本身都在记录和更新当前的时间,也就是说系统时间和RTC时间是两套独立的计时机制。简单的说就是——RTC时间才是真正持续更新,而操作系统则是只有在系统启动以后才会持续更新,在操作系统关闭或重启期间,甚至服务器下电期间,整个服务器的时间就依赖于RTC了。
NTP服务器列表
域名 | IP地址 |
time-a.nist.gov | 129.6.15.28 |
time-b.nist.gov | 129.6.15.29 |
time-a.timefreq.bldrdoc.gov | 132.163.4.101 |
time-b.timefreq.bldrdoc | 132.163.4.102 |
time-c.timefreq.bldrdoc.gov | 132.163.4.103 |
utcnist.colorado.edu | 128.138.140.44 |
time.nist.gov | 192.43.244.18 |
time-nw.nist.gov | 131.107.1.10 |
nist1.datum.com | 66.243.43.21 |
nist1-dc.glassey.com | 216.200.93.8 |
nist1-ny.glassey.com | 208.184.49.9 |
nist1-sj.glassey.com | 207.126.98.204 |
nist1.aol-ca.truetime.com | 207.200.81.113 |
nist1.aol-va.truetime.com | 205.188.185.33 |
国家授时 | 210.72.145.44 |
ntppool提供了各个地区的NTP池,我测试了几个,发现巴西的https://www.pool.ntp.org/zone/br (200.20.186.76)比较好用。
代码实现如下:
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <iostream>
#define LOG(...) \
{ \
fprintf(stderr, "{{%s: Line %d:}}\t", __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
}
void ntpdate();
int main() {
ntpdate();
return 0;
}
void ntpdate() {
char *hostname = (char *)"200.20.186.76"; // pool.ntp.br NTP server IP
int portno = 123; // NTP is port 123
int maxlen = 1024; // check our buffers
int i; // misc var i
unsigned char msg[48] = {010, 0, 0, 0, 0, 0, 0, 0, 0}; // the packet we send
unsigned long buf[maxlen]; // the buffer we get back
// struct in_addr ipaddr;
struct protoent *proto; //
struct sockaddr_in server_addr;
int s; // socket
long tmit; // the time -- This is a time_t sort of
LOG("200.20.186.76 has been setted!!");
// use Socket;
//
//#we use the system call to open a UDP socket
// socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!";
proto = getprotobyname("udp");
s = socket(PF_INET, SOCK_DGRAM, proto->p_proto);
perror("socket");
//#convert hostname to ipaddress if needed
//$ipaddr = inet_aton($HOSTNAME);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(hostname);
server_addr.sin_port = htons(portno);
/*
* build a message. Our message is all zeros except for a one in the
* protocol version field
* msg[] in binary is 00 001 000 00000000
* it should be a total of 48 bytes long
*/
// send the data
printf("sending data..\n");
i = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
perror("sendto");
// get the data back
struct sockaddr saddr;
socklen_t saddr_l = sizeof(saddr);
i = recvfrom(s, buf, 48, 0, &saddr, &saddr_l);
perror("recvfr:");
/*
* The high word of transmit time is the 10th word we get back
* tmit is the time in seconds not accounting for network delays which
* should be way less than a second if this is a local NTP server
*/
tmit = ntohl((time_t)buf[4]); //# get transmit time
/*
* Convert time to unix standard time NTP is number of seconds since 0000
* UT on 1 January 1900 unix time is seconds since 0000 UT on 1 January
* 1970 There has been a trend to add a 2 leap seconds every 3 years.
* Leap seconds are only an issue the last second of the month in June and
* December if you don't try to set the clock then it can be ignored but
* this is importaint to people who coordinate times with GPS clock sources.
*/
tmit -= 2208988800U;
std::cout << "remote time is " << ctime(&tmit) << std::endl;
char bufCurrentTime[32];
char currentTime[64] = "date -s ";
strftime(bufCurrentTime, sizeof(bufCurrentTime) - 1, " '%H:%M:%S %Y-%m-%d' ", localtime(&tmit));
std::cout << "bufCurrentTime:" << bufCurrentTime << std::endl;
for (int i = 0; i < 32; i++) {
currentTime[8 + i] = bufCurrentTime[i];
}
std::cout << "currentTime:" << currentTime << std::endl;
int setInSuccess = system(currentTime);
if (setInSuccess != 0) {
LOG("setTime is fail");
}
i = time(0);
std::cout << "System time is " << (i - tmit) << " seconds off" << std::endl;
return 0;
}
可能会报如下错误:
patten@patten-hp:~/diskTwo/demoCode/cppTime$ g++ getTime.cpp
patten@patten-hp:~/diskTwo/demoCode/cppTime$ ./a.out
socket: Success
sending data..
sendto: Success
recvfr:: Success
time is Wed Jun 19 15:33:51 2019
currentTime:date -s 2019/06/19
date: 无法设置日期: 不允许的操作
2019年 06月 19日 星期三 00:00:00 CST
{{getTime.cpp: Line 103:}} setTime is fail
System time is -198251 seconds off
主要原因在于执行system指令时权限不够,所以执行该程序时,应该拥有root权限。
C++perror函数
- C++中的errno变量,是用来记录错误类型。当调用,某些函数出错时,会自动设置errno的值。此时,可以利用perror,将errno错误输出。
- 作用:将上一个函数发生的错误原因,输出到标准设备.
代码解析:
// 头文件
#include <stdio.h>
/* 函数原型
* 参数str,指定要输出的字符串
* 如 perror("Error:")
* 输出 Error: error message
*/
void perror (const char* str)
// 例子
#include <stdio.h>
int main()
{
FILE* fp;
fp = fopen("/xxx/xxx", "r+");
if (NULL == fp) {
perror("Error: ");
}
return 0;
}
关联文章: