【SNTP协议简介】
在一些特定的场景中,经常需要整个网络中的计算机保持时间同步。例如,空中管制系统或者轨道交通控制系统中的计算机的时间需要保持精确同步。在大型计算机系统中,往往由很多台计算机共同执行某个计算,也需要各台计算机保持时间同步。那么,我们通过什么方法来同步这些计算机的时间呢?
科学家发明了一种叫做NTP的网络时间协议。网络时间协议是一种在网络计算机上同步计算机时间的的协议,它具有高度的精确性(能精确到几十毫秒),但是算法非常复杂。实际上,在很多应用场景中,并不需要这么高的精确度,通常只要达到秒级的精确度就足够了。于是,科学家在NTP的基础上推出了SNTP(简单网络时间协议,Simple
Network Time Protocol)。SNTP大大简化了NTP协议,同时也能保证时间达到一定的精确度。在实际应用中,SNTP协议主要被用来同步因特网上计算机的时间。
夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。
【注意事项】
中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。
【工作原理】
SNTP协议采用客户端/服务器的工作方式,可以采用单播(点对点)或者广播(一点对多点)模式操作。SNTP服务器通过接收GPS信号或自带的原子钟作为系统的时间基准。单播模式下,SNTP客户端能够通过定期访问SNTP服务器获得准确的时间信息,用于调整客户端自身所在系统的时间,达到同步时间的目的。广播模式下,SNTP服务器周期性地发送消息给指定的IP广播地址或者IP多播地址。SNTP客户端通过监听这些地址来获得时间信息。
网络中一般存在很多台SNTP服务器,客户端会通过一定的算法选择最好的几台服务器使用。如果一台SNTP服务器在工作过程中失去了外部时间源,此时SNTP服务器会告诉SNTP客户端“我失去了外部时间”。当SNTP客户端收到这个信息时,就会丢弃发生故障的SNTP服务器发给它的时间信息,然后重新选择其他的SNTP服务器。
【相关API】
头文件:qcom/qcom_sntp.h
void qcom_enable_sntp_client(int enable); //使能或关闭SNTP客户端
void qcom_sntp_srvr_addr(int flag,char* srv_addr); //配置SNTP服务器的地址
void qcom_sntp_zone(int hour,int min,int add_sub,int enable);//配置SNTP时区
void qcom_sntp_get_time(A_UINT8 device_id, tSntpTime* time); //获取SNTP时间
void qcom_sntp_show_config(); //查看配置信息
void qcom_sntp_get_time_of_day(A_UINT8 device_id, tSntpTM* time);//获取时间
void qcom_sntp_query_srvr_address(A_UINT8 device_id, SNTP_QUERY_SRVR_ADDRESS* addr); //查询SNTP地址
【编程步骤】
1. 使能sntp客户端
2. 配置sntp的时区信息
3. 获取sntp的时间
【注意】
ceac_sntp_client_enable(DEV_ID, 1);
qcom_thread_msleep(5000); //前后一定要睡眠 否则获取的时间是默认的
ceac_config_sntp_zone(DEV_ID, "UTC+08:00", "enable") ;
qcom_thread_msleep(5000) //前后一定要睡眠 否则获取的时间是默认的
ceac_sntp_show_information(DEV_ID);
ceac_sntp_get_time(DEV_ID);
测试的时候,要确保开发板已经连接上Wifi,否则获取的时间值是默认的时间值。
【参考代码】
第一步:sntp客户端使能
/* *@function: enable sntp client * *@param: 1:enable 0: disable * *@return none */ void ceac_sntp_client_enable(A_UINT8 device_id, int enable) { //enable SNTP at run time qcom_enable_sntp_client(enable); }
第二步:设置sntp的时区信息
/* *@function: Configure SNTP time zone and enable/disable day light saving * *@param: utc eg:UTC+05:30 *@param: dls_en "disable" or enable *@return none */ void ceac_config_sntp_zone(A_UINT8 device_id, A_CHAR* utc, A_CHAR* dls_en) { int flag = 0; int hour = 0, min = 0; int add_sub; char hr[3], mn[3], parsing_hour_min[10]; if (A_STRLEN(utc) > 9) { A_PRINTF("Error : Invalid UTC string. Valid string(UTC+hour:min).Eg UTC+05:30\n\r"); return; } if (A_STRLEN(dls_en) > 8) { A_PRINTF("Error : Invalid DSE string.Valid string enable/disable \n\r"); } A_STRCPY(parsing_hour_min, utc); //UTC+xx:xx or UTC-xx:xx if (A_STRLEN(parsing_hour_min) != 9) { A_PRINTF("Error : UTC time format should be UTC+XX:XX or UTC-XX:XX\n"); A_PRINTF("Hour from 00 to -12/+13, minute should be 0, 30 or 45\n\r"); return; } //parse the hour hr[0] = parsing_hour_min[4]; hr[1] = parsing_hour_min[5]; hr[2] = '\0'; hour = (hr[0] - '0') * 10 + (hr[1] - '0'); //parse the minues mn[0] = parsing_hour_min[7]; mn[1] = parsing_hour_min[8]; mn[2] = '\0'; min = (mn[0] - '0') * 10 + (mn[1] - '0'); if (0 != min && 30 != min && 45 != min) { A_PRINTF("Error : UTC time offset in minutes should be 0, 30 or 45\n\r"); return; } //valid time zone: -12,-11, ...., +13 if ('+' == parsing_hour_min[3]) { add_sub = 1; // time is to be added if (hour > 13 || ((13 == hour) && (min > 0))) { A_PRINTF("Error : UTC time offset in hour from -12 to +13\n\r"); return; } } else if ('-' == parsing_hour_min[3]) { add_sub = 0; // time is to be substracted if((hour > 12) || ((12 == hour) && (min > 0))) { A_PRINTF("Error : UTC time offset in hour from -12 to +13\n\r"); return; } } else { A_PRINTF("Error: Only +/- operation is allowed\n"); return ; } //wether disable or enable day light saving if (!A_STRCMP(dls_en, "enable")) flag = 1; //enable else if (!A_STRCMP(dls_en, "disable")) flag = 0; else { A_PRINTF("DSE(day light saving) input parameter should be enable or disable !\n"); return; } A_PRINTF("------>qcom_sntp_zone hour: %d min: %d add_sub: %d flag: %d\n", hour, min, add_sub, flag); qcom_sntp_zone(hour, min, add_sub, flag); return; }
第三步:获取时间
/* *@function: Get SNTP time * * *@return none */ void ceac_sntp_get_time(A_UINT8 device_id) { tSntpTime time; char *months[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; char *Day[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; qcom_sntp_get_time(device_id, &time); A_PRINTF("\nRTC TimeStamp: %s %s %d %d %d:%d:%d\n", Day[time.wday], months[time.mon], time.yday, time.year, time.hour, time.min, time.Sec); return; }
第四步:测试程序
void sntp_task(unsigned long which_thread) { // just test SNTP client #define DEV_ID 0 ceac_sntp_client_enable(DEV_ID, 1); //Note that: must sleep serval seconds, or it will config error qcom_thread_msleep(5000); ceac_config_sntp_zone(DEV_ID, "UTC+08:00", "enable") ; qcom_thread_msleep(5000); ceac_sntp_get_time(DEV_ID); }
【测试环境】
Win7 + QCA4010开发板 + Xshell
【测试结果】
显示当前正确的时间