綏化市建設(shè)工程網(wǎng)站招投標(biāo)app推廣公司怎么對(duì)接業(yè)務(wù)
NTP(Network Time Protocol,網(wǎng)絡(luò)時(shí)間協(xié)議)是由RFC 1305定義的時(shí)間同步協(xié)議。它是通過(guò)網(wǎng)絡(luò)在計(jì)算機(jī)系統(tǒng)之間進(jìn)行時(shí)鐘同步的網(wǎng)絡(luò)協(xié)議。NTP 在公共互聯(lián)網(wǎng)上通常能夠保持時(shí)間延遲在幾十毫秒以內(nèi)的精度,并在理想條件下,它能在局域網(wǎng)下達(dá)到低于一毫秒的延遲精度。它使用用戶數(shù)據(jù)報(bào)協(xié)議(UDP)在端口 123 上發(fā)送和接受時(shí)間戳。它是個(gè) C/S 架構(gòu)的應(yīng)用程序。
NTP工作原理
NTP的基本工作原理如圖所示。Device A和Device B通過(guò)網(wǎng)絡(luò)相連,它們都有自己獨(dú)立的系統(tǒng)時(shí)鐘,需要通過(guò)NTP實(shí)現(xiàn)各自系統(tǒng)時(shí)鐘的自動(dòng)同步。為便于理解,作如下假設(shè):
·在Device A和Device B的系統(tǒng)時(shí)鐘同步之前,Device A的時(shí)鐘設(shè)定為10:00:00am,Device B的時(shí)鐘設(shè)定為11:00:00am。
·Device B作為NTP時(shí)間服務(wù)器,即Device A將使自己的時(shí)鐘與Device B的時(shí)鐘同步。
·NTP報(bào)文在Device A和Device B之間單向傳輸所需要的時(shí)間為1秒。
系統(tǒng)時(shí)鐘同步的工作過(guò)程如下:
·Device A發(fā)送一個(gè)NTP報(bào)文給Device B,該報(bào)文帶有它離開(kāi)Device A時(shí)的時(shí)間戳,該時(shí)間戳為10:00:00am(T1)。
·當(dāng)此NTP報(bào)文到達(dá)Device B時(shí),Device B加上自己的時(shí)間戳,該時(shí)間戳為11:00:01am(T2)。
·當(dāng)此NTP報(bào)文離開(kāi)Device B時(shí),Device B再加上自己的時(shí)間戳,該時(shí)間戳為11:00:02am(T3)。
·當(dāng)Device A接收到該響應(yīng)報(bào)文時(shí),Device A的本地時(shí)間為10:00:03am(T4)。
至此,Device A已經(jīng)擁有足夠的信息來(lái)計(jì)算兩個(gè)重要的參數(shù):
·NTP報(bào)文的往返時(shí)延Delay=(T4-T1)-(T3-T2)=2秒。
·Device A相對(duì)Device B的時(shí)間差offset=((T2-T1)+(T3-T4))/2=1小時(shí)。
這樣,Device A就能夠根據(jù)這些信息來(lái)設(shè)定自己的時(shí)鐘,使之與Device B的時(shí)鐘同步。
以上內(nèi)容只是對(duì)NTP工作原理的一個(gè)粗略描述.
/*** T1,客戶端發(fā)送請(qǐng)求時(shí)的 本地系統(tǒng)時(shí)間戳;* T2,服務(wù)端接收到客戶端請(qǐng)求時(shí)的 本地系統(tǒng)時(shí)間戳;* T3,服務(wù)端發(fā)送應(yīng)答數(shù)據(jù)包時(shí)的 本地系統(tǒng)時(shí)間戳;* T4,客戶端接收到服務(wù)端應(yīng)答數(shù)據(jù)包時(shí)的 本地系統(tǒng)時(shí)間戳。*/
NTP 報(bào)文格式
/** Dissecting NTP packets version 3 and 4 (RFC5905, RFC2030, RFC1769, RFC1361,* RFC1305).** Those packets have simple structure:* 1 2 3* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* |LI | VN |Mode | Stratum | Poll | Precision |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Root Delay |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Root Dispersion |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Reference Identifier |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Reference Timestamp (64) |* | |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Originate Timestamp (64) |* | |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Receive Timestamp (64) |* | |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Transmit Timestamp (64) |* | |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Key Identifier (optional) (32) |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Message Digest (optional) (128/160) |* | |* | |* | |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* NTP timestamps are represented as a 64-bit unsigned fixed-point number,* in seconds relative to 0h on 1 January 1900. The integer part is in the* first 32 bits and the fraction part in the last 32 bits.*** NTP Control messages as defined in version 2, 3 and 4 (RFC1119, RFC1305) use* the following structure:* 1 2 3* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* |00 | VN | 110 |R E M| OpCode | Sequence |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Status | Association ID |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Offset | Count |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | |* | Data (468 octets max) |* | |* | | Padding (zeros) |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+* | Authenticator (optional) (96) |* | |* | |* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+** Not yet implemented: complete dissection of TPCTRL_OP_SETTRAP,* NTPCTRL_OP_ASYNCMSG, NTPCTRL_OP_UNSETTRAPSETTRAP Control-Messages**/
NTP Version 3
NTP Version 4
它的字段含義參考如下:
LI 閏秒標(biāo)識(shí)器,占用2個(gè)bit
VN 版本號(hào),占用3個(gè)bits,表示NTP的版本號(hào),現(xiàn)在為3
Mode 模式,占用3個(gè)bits,表示模式
stratum(層),占用8個(gè)bits
Poll 測(cè)試間隔,占用8個(gè)bits,表示連續(xù)信息之間的最大間隔
Precision 精度,占用8個(gè)bits,,表示本地時(shí)鐘精度
Root Delay根時(shí)延,占用8個(gè)bits,表示在主參考源之間往返的總共時(shí)延
Root Dispersion根離散,占用8個(gè)bits,表示在主參考源有關(guān)的名義錯(cuò)誤
Reference Identifier參考時(shí)鐘標(biāo)識(shí)符,占用8個(gè)bits,用來(lái)標(biāo)識(shí)特殊的參考源
參考時(shí)間戳,64bits時(shí)間戳,本地時(shí)鐘被修改的最新時(shí)間。
原始時(shí)間戳,客戶端發(fā)送的時(shí)間,64bits。
接受時(shí)間戳,服務(wù)端接受到的時(shí)間,64bits。
傳送時(shí)間戳,服務(wù)端送出應(yīng)答的時(shí)間,64bits。
認(rèn)證符(可選項(xiàng))
NTP的工作模式
NTP支持以下幾種工作模式:
1.客戶端/服務(wù)器模式2.對(duì)等體模式3.廣播模式4.組播模式
用戶可以根據(jù)需要選擇一種或幾種工作模式進(jìn)行時(shí)間同步,我們主要講解客戶端/服務(wù)器模式。
工作過(guò)程:
客戶端上需要手工指定NTP服務(wù)器的地址??蛻舳讼騈TP服務(wù)器發(fā)送NTP時(shí)間同步報(bào)文。NTP服務(wù)器收到報(bào)文后會(huì)自動(dòng)工作在服務(wù)器模式,并回復(fù)應(yīng)答報(bào)文如果客戶端可以從多個(gè)時(shí)間服務(wù)器獲取時(shí)間同步,則客戶端收到應(yīng)答報(bào)文后,進(jìn)行時(shí)鐘過(guò)濾和選擇,并與優(yōu)選的時(shí)鐘進(jìn)行時(shí)間同步
一些常用的 NTP 服務(wù)器地址:
ntp.tencent.com
ntp1.tencent.com
ntp2.tencent.com
ntp3.tencent.com
ntp4.tencent.com
ntp5.tencent.com
ntp.aliyun.com
ntp1.aliyun.com
ntp2.aliyun.com
ntp3.aliyun.com
ntp4.aliyun.com
ntp5.aliyun.com
ntp6.aliyun.com
ntp7.aliyun.com
time.edu.cn
s2c.time.edu.cn
s2f.time.edu.cn
NTP客戶端連接服務(wù)器獲取網(wǎng)絡(luò)時(shí)間戳
typedef enum xntp_mode_t
{ntp_mode_unknow = 0, ///< 未定義ntp_mode_initiative = 1, ///< 主動(dòng)對(duì)等體模式ntp_mode_passive = 2, ///< 被動(dòng)對(duì)等體模式ntp_mode_client = 3, ///< 客戶端模式ntp_mode_server = 4, ///< 服務(wù)器模式ntp_mode_broadcast = 5, ///< 廣播模式或組播模式ntp_mode_control = 6, ///< 報(bào)文為 NTP 控制報(bào)文ntp_mode_reserved = 7, ///< 預(yù)留給內(nèi)部使用
} xntp_mode_t;static x_void_t output_tu(x_cstring_t xszt_info, xtime_vnsec_t xtm_vnsec)
{printf("%s : ", xszt_info);output_ns(xtm_vnsec);printf("\n");
}/**********************************************************/
/***打上信息標(biāo)號(hào),輸出 NTP 時(shí)間戳 的 具體時(shí)間信息。*/
static x_void_t output_tm(x_cstring_t xszt_info, xtime_stamp_t * xtm_stamp)
{printf("%s : ", xszt_info);output_ts(xtm_stamp);printf("\n");
}...
xtime_vnsec_t ntpcli_get_time(x_cstring_t xszt_host,x_uint16_t xut_port,x_uint32_t xut_tmout)
{x_int32_t xit_errno = EPERM;xtime_vnsec_t xtm_vnsec = XTIME_INVALID_VNSEC;xntp_cliptr_t xntp_this = X_NULL;do{xntp_this = ntpcli_open();if (X_NULL == xntp_this){break;}xit_errno = ntpcli_config(xntp_this, xszt_host, xut_port);if (0 != xit_errno){errno = xit_errno;break;}xtm_vnsec = ntpcli_req_time(xntp_this, xut_tmout);} while (0);if (X_NULL != xntp_this){ntpcli_close(xntp_this);xntp_this = X_NULL;}return xtm_vnsec;
}
/**********************************************************/
/***初始化 NTP 的請(qǐng)求數(shù)據(jù)包。*/
static x_void_t ntp_init_req_packet(xntp_pack_t * xnpt_dptr)
{
...xnpt_dptr->xct_lvmflag = NTP_LI_VN_MODE(0, 3, ntp_mode_client);xnpt_dptr->xct_stratum = 0;xnpt_dptr->xct_ppoll = 4;xnpt_dptr->xct_percision = (x_char_t)(-6);xnpt_dptr->xut_rootdelay = (1 << 16);xnpt_dptr->xut_rootdisp = (1 << 16);xnpt_dptr->xut_refid = 0;xnpt_dptr->xtms_reference.xut_seconds = 0;xnpt_dptr->xtms_reference.xut_fraction = 0;xnpt_dptr->xtms_originate.xut_seconds = 0;xnpt_dptr->xtms_originate.xut_fraction = 0;xnpt_dptr->xtms_receive .xut_seconds = 0;xnpt_dptr->xtms_receive .xut_fraction = 0;xnpt_dptr->xtms_transmit .xut_seconds = 0;xnpt_dptr->xtms_transmit .xut_fraction = 0;
}/**********************************************************/
/*** 發(fā)送 NTP 請(qǐng)求,獲取服務(wù)器時(shí)間戳。*/
xtime_vnsec_t ntpcli_req_time(xntp_cliptr_t xntp_this, x_uint32_t xut_tmout)
{x_int32_t xit_errno = EPERM;// 參數(shù)驗(yàn)證if (X_NULL == xntp_this){errno = EINVAL;return XTIME_INVALID_VNSEC;}if (name_is_ipv4(xntp_this->xszt_host, X_NULL))xit_errno = ntpcli_get_4T(xntp_this, xntp_this->xszt_host, xut_tmout);elsexit_errno = ntpcli_get_4T_by_name(xntp_this, xut_tmout);if (0 != xit_errno){errno = xit_errno;return XTIME_INVALID_VNSEC;}return ntp_calc_4T(xntp_this->xtm_4time);
}/** 常用的 NTP 服務(wù)器地址列表 */
x_cstring_t xszt_host[] =
{"ntp.tencent.com" ,"ntp1.tencent.com","ntp2.tencent.com","ntp3.tencent.com","ntp4.tencent.com","ntp5.tencent.com","ntp1.aliyun.com" ,"ntp2.aliyun.com" ,"ntp3.aliyun.com" ,"ntp4.aliyun.com" ,"ntp5.aliyun.com" ,"ntp6.aliyun.com" ,"ntp7.aliyun.com" ,"time.edu.cn" ,"s2c.time.edu.cn" ,"s2f.time.edu.cn" ,"s2k.time.edu.cn" ,X_NULL
};/** 網(wǎng)絡(luò)地址(IP 或 域名)類型 */
typedef x_char_t x_host_t[TEXT_LEN_256];/*** 命令選項(xiàng)的各個(gè)參數(shù)。*/
typedef struct xopt_args_t
{x_bool_t xbt_usage; ///< 是否顯示幫助信息x_uint16_t xut_port; ///< NTP 服務(wù)器端口號(hào)(默認(rèn)值為 123)x_host_t xntp_host; ///< NTP 服務(wù)器地址x_int32_t xit_rept; ///< 請(qǐng)求重復(fù)次數(shù)(默認(rèn)值為 1)x_uint32_t xut_tmout; ///< 網(wǎng)絡(luò)請(qǐng)求的超時(shí)時(shí)間(單位為 毫秒,默認(rèn)值取 3000)
} xopt_args_t;/** 簡(jiǎn)單的判斷 xopt_args_t 的有效性 */
#define XOPT_VALID(xopt) (('\0' != (xopt).xntp_host[0]) && ((xopt).xit_rept > 0))/**********************************************************/
/*** 字符串忽略大小寫(xiě)的比對(duì)操作。*/
static x_int32_t xstr_icmp(x_cstring_t xszt_lcmp, x_cstring_t xszt_rcmp)
{x_int32_t xit_lvalue = 0;x_int32_t xit_rvalue = 0;if (xszt_lcmp == xszt_rcmp)return 0;if (X_NULL == xszt_lcmp)return -1;if (X_NULL == xszt_rcmp)return 1;do{if (((xit_lvalue = (*(xszt_lcmp++))) >= 'A') && (xit_lvalue <= 'Z'))xit_lvalue -= ('A' - 'a');if (((xit_rvalue = (*(xszt_rcmp++))) >= 'A') && (xit_rvalue <= 'Z'))xit_rvalue -= ('A' - 'a');} while (xit_lvalue && (xit_lvalue == xit_rvalue));return (xit_lvalue - xit_rvalue);
}/**********************************************************/
/***顯示應(yīng)用程序的 命令行格式。*/
x_void_t usage(x_cstring_t xszt_app)
{x_int32_t xit_iter = 1;printf("Usage:\n %s [-h] [-n <number>] -s <host> [-p <port>] [-t <msec>]\n", xszt_app);printf("\t-h Output usage.\n");printf("\t-n <number> The times of repetition.\n");printf("\t-s <host> The host of NTP server, IP or domain.\n");printf("\t-p <port> The port of NTP server, default 123.\n");printf("\t-t <msec> Network request timeout in milliseconds, default 3000.\n");printf("\nCommon NTP server:\n");for (xit_iter = 0; X_NULL != xszt_host[xit_iter]; ++xit_iter){printf("\t%s\n", xszt_host[xit_iter]);}printf("\n");
}/**********************************************************/
/*** 從命令行中,提取工作的選項(xiàng)參數(shù)信息。*/
x_void_t get_opt(x_int32_t xit_argc, x_cstring_t xszt_argv[], xopt_args_t * xopt_args)
{
...for (; xit_iter < xit_argc; ++xit_iter){if (!xopt_args->xbt_usage && (0 == xstr_icmp("-h", xszt_argv[xit_iter]))){xopt_args->xbt_usage = X_TRUE;}else if (0 == xstr_icmp("-s", xszt_argv[xit_iter])){if ((xit_iter + 1) < xit_argc){
...}}else if (0 == xstr_icmp("-n", xszt_argv[xit_iter])){if ((xit_iter + 1) < xit_argc)xopt_args->xit_rept = atoi(xszt_argv[++xit_iter]);}else if (0 == xstr_icmp("-p", xszt_argv[xit_iter])){if ((xit_iter + 1) < xit_argc)xopt_args->xut_port = (x_uint16_t)atoi(xszt_argv[++xit_iter]);}else if (0 == xstr_icmp("-t", xszt_argv[xit_iter])){if ((xit_iter + 1) < xit_argc)xopt_args->xut_tmout = (x_uint32_t)atoi(xszt_argv[++xit_iter]);}}
}int main(int argc, char * argv[])
{
...do{get_opt(argc, argv, &xopt_args);if (!XOPT_VALID(xopt_args)){usage(argv[0]);break;}if (xopt_args.xbt_usage){usage(argv[0]);}xntp_this = ntpcli_open();if (X_NULL == xntp_this){printf("ntpcli_open() return X_NULL, errno : %d\n", errno);break;}ntpcli_config(xntp_this, xopt_args.xntp_host, xopt_args.xut_port);for (xit_iter = 0; xit_iter < xopt_args.xit_rept; ++xit_iter){xtm_vnsec = ntpcli_req_time(xntp_this, xopt_args.xut_tmout);if (XTMVNSEC_IS_VALID(xtm_vnsec)){xtm_ltime = time_vnsec();xtm_descr = time_vtod(xtm_vnsec);xtm_local = time_vtod(xtm_ltime);printf("\n[%d] %s:%d : \n",xit_iter + 1,xopt_args.xntp_host,xopt_args.xut_port);printf("\tNTP response : [ %04d-%02d-%02d %d %02d:%02d:%02d.%03d ]\n",xtm_descr.ctx_year ,xtm_descr.ctx_month ,xtm_descr.ctx_day ,xtm_descr.ctx_week ,xtm_descr.ctx_hour ,xtm_descr.ctx_minute,xtm_descr.ctx_second,xtm_descr.ctx_msec );printf("\tLocal time : [ %04d-%02d-%02d %d %02d:%02d:%02d.%03d ]\n",xtm_local.ctx_year ,xtm_local.ctx_month ,xtm_local.ctx_day ,xtm_local.ctx_week ,xtm_local.ctx_hour ,xtm_local.ctx_minute,xtm_local.ctx_second,xtm_local.ctx_msec );printf("\tDeviation : %lld us\n",((x_int64_t)(xtm_ltime - xtm_vnsec)) / 10LL);}else{printf("\n[%d] %s:%d : errno = %d\n",xit_iter + 1,xopt_args.xntp_host,xopt_args.xut_port,errno);}}} while (0);if (X_NULL != xntp_this){ntpcli_close(xntp_this);xntp_this = X_NULL;}
...return 0;
}
...
運(yùn)行結(jié)果:
If you need the complete source code, please add the WeChat number (c17865354792)
在客戶端/服務(wù)器模式中,客戶端向服務(wù)器發(fā)送時(shí)鐘同步報(bào)文,報(bào)文中的Mode字段設(shè)置為3(客戶模式)。服務(wù)器端收到報(bào)文后會(huì)自動(dòng)工作在服務(wù)器模式,并發(fā)送應(yīng)答報(bào)文,報(bào)文中的Mode字段設(shè)置為4(服務(wù)器模式)??蛻舳耸盏綉?yīng)答報(bào)文后,進(jìn)行時(shí)鐘過(guò)濾和選擇,并同步到優(yōu)選的服務(wù)器。
在該模式下,客戶端能同步到服務(wù)器,而服務(wù)器無(wú)法同步到客戶端。
- tcpdump抓包分析
NTP協(xié)議應(yīng)用于分布式時(shí)間服務(wù)器和客戶端之間,實(shí)現(xiàn)客戶端和服務(wù)器的時(shí)間同步,從而使網(wǎng)絡(luò)內(nèi)所有設(shè)備的時(shí)鐘基本保持一致。下面的報(bào)文是客戶端連接服務(wù)器時(shí)產(chǎn)生的交互過(guò)程。
- NTP協(xié)議解析
If you need the complete source code, please add the WeChat number (c17865354792)
總結(jié)
NTP客戶端啟動(dòng)與NTP服務(wù)器的時(shí)間請(qǐng)求交換。交換的結(jié)果是,客戶端能夠計(jì)算鏈路延遲及其本地偏移,并調(diào)整其本地時(shí)鐘以匹配服務(wù)器計(jì)算機(jī)上的時(shí)鐘。
Welcome to follow WeChat official account【程序猿編碼】
參考:1.RFC 1305
2.http://ntp.neu.edu.cn/archives/92/
3.http://ntp.neu.edu.cn/archives/95