开源代码下载地址:https://codeload.github.com/yuanrw/tcp-server-client/zip/master
下载后可以直接根据Readme编译linux版本运行

ntp_client

使用NTP协议获取网络时间戳,提供的 C/C++ 源码支持 Windows 和 Linux(CentOS) 两大平台。

Winodws 平台上编译与测试

在 VC 的命令行环境下,使用 nmake /f Makefile.mk 命令进行编译,输出的测试程序为
ntp_cli_test.exe ,执行该程序,即可看到测试结果。

Linux 平台上编译与测试

# make
# ./ntp_cli_test

依次执行上面的命令,即可看到测试结果。

源码说明

  • VxDType.h: 定义通用数据类型的头文件。
  • VxNtpHelper.h:使用NTP协议获取网络时间戳所提供的 API 与相关数据定义的头文件。
  • VxNtpHelper.cpp:VxNtpHelper.h中提供的操 API 实现源码文件。
  • main.cpp:接口调用流程(测试程序)。

测试程序的输出样例信息如下:

  1.cn.pool.ntp.org -> 193.228.143.22

        time1 : 2018-11-16_18-43-43.126
        time2 : 2018-11-16_18-43-43.245
        time3 : 2018-11-16_18-43-43.245
        time4 : 2018-11-16_18-43-43.419
        timev : 2018-11-16_18-43-43.391
        timec : 2018-11-16_18-43-43.419
        1.cn.pool.ntp.org : 2018-11-16_18-43-43.391
  • time1 : 客户端 发送一个NTP报文给 服务端,该报文带有它离开 客户端 时的时间戳 (T1)。
  • time2 : 当此NTP报文到达 服务端 时,服务端 加上自己的时间戳 (T2)。
  • time3 : 当此NTP报文离开 服务端 时,服务端 再加上自己的时间戳 (T3)。
  • time4 : 当 客户端 接收到该应答报文时,客户端 的本地时间戳 (T4)。
  • timev : 同步到的时间戳 T = T4 + ((T2 - T1) + (T3 - T4)) / 2;
  • timec : 系统当前的时间。

具体项目中的应用,参看 main.cpp 中的调用流程。

定义成接口

头文件:
/**

  • @brief 获取服务器时间。
  • @param [in ] value : 对应不同的ntp服务域名
  • @param [in ] *result : 调用接口的结果,0:success
  • @return x_int64_t
  •     - 成功,返回 时间;
    
  •     - 失败,返回 0。
    

*/
x_uint64_t getNtpTime(int value,int *result);

cpp文件:
x_uint64_t getNtpTime(int value,int *result)
{
int xit_err = -1;
x_ntp_time_context_t xnpt_timec;
memset(&xnpt_timec,0,sizeof(xnpt_timec));
x_uint64_t xut_timev = 0ULL;

//======================================
std::vector< std::string > xvec_ntp_host;
switch(value)
{
    case 0:
        xvec_ntp_host.push_back(std::string("0.cn.pool.ntp.org"));
        break;
    case 1:
        xvec_ntp_host.push_back(std::string("1.cn.pool.ntp.org"));
        break;
    case 2:
        xvec_ntp_host.push_back(std::string("2.cn.pool.ntp.org"));
        break;
    case 3:
        xvec_ntp_host.push_back(std::string("3.cn.pool.ntp.org"));
        break;

    default:
        xvec_ntp_host.push_back(std::string("cn.pool.ntp.org"));
        break;
}
//======================================

for (std::vector< std::string >::iterator itvec = xvec_ntp_host.begin(); itvec != xvec_ntp_host.end(); ++itvec)
{
    xut_timev = 0ULL;
    xit_err = ntp_get_time(itvec->c_str(), NTP_PORT, 5000, &xut_timev);
    memcpy(result,&xit_err,sizeof(xit_err));
    if (0 == xit_err)
    {
        printf("xut_timev = %lld\n", xut_timev);
        ntp_tmctxt_bv(xut_timev, &xnpt_timec);   // 转换成 年-月-日_时-分-秒.毫秒 的时间信息
        ts_output(itvec->c_str(), &xnpt_timec);  // 输出时间信息
    }
    else
    {
        // 请求失败,可能是因为应答超时......
        printf("  %s return error code : %d\n", itvec->c_str(), xit_err);
    }
}

//======================================

return xut_timev;

}

由其他函数调用

#include “VxNtpHelper.h”

#if 1
x_uint64_t ntpTime;
struct timespec tmp;
int ntpResult=-1;
int setSystemTimeRsult=-1;

memset(&ntpTime,0,sizeof(ntpTime));
memset(&tmp,0,sizeof(tmp));

//Set Android time zone
system("setprop persist.sys.timezone CST+8");

for(int i=0;i<repeatCount;i++)
{
    ntpTime = getNtpTime(i,&ntpResult);//单位为100ns
    if(ntpResult == 0)
        break;
    else
    if(ntpResult == 7 || ntpResult == 11)
        printf("getNtpTime() ntpResult = %d ntpTime = %d : 请检查网络连接 , repeat 3 times : No.%d \n",ntpResult,ntpTime,i+1);
    else
        printf("getNtpTime() ntpResult = %d \n", ntpResult);
}

if(ntpResult == 0)
{
    tmp.tv_sec  = ntpTime/10000000;
    tmp.tv_nsec = (ntpTime%10000000)*100;

    for(int nCount=0;nCount<repeatCount;nCount++)
    {
        if(clock_settime(CLOCK_REALTIME, &tmp))//-1
        {
          perror("setclock mtime error");
        }
        else//0
        {
          printf("setclock success \n");
          break;
        }
    }
}

#endif

编译生成可执行文件

生成android可以运行的程序(aarch64-linux-android-g++请自行安装环境)
aarch64-linux-android-g++ xx.cpp main.cpp xx.c VxDType.h VxNtpHelper.h VxNtpHelper.cpp -o test_Android_netTime -fPIE -pie

设置时区

时间同步后假如时间与看到网络时间不一致(一般多或少8个小时),这是因为时区不对
可按下面的方法设置时区:
QNX设置时区:env TZ=CTS-8 && export TZ=CST-8 && setconf_CS_TIMEZONE CTS-8
Android设置时区:setprop persist.sys.timezone CST+8
根据当前所处地区的所处时区再做对应修改

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐