分享
 
 
 

网络同步校时(RFC868/C++/WIN32/SOCKET)

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

前一段时间我单位的几十台工业机需要同步校时, 故去察看了RFC868, 我就试编了一个获得网络时间的小程序, 大家可以借鉴到自己的同步校时程序, 只是试验,所以程序结构并不严谨, 过一段时间我会把服务器段的代码贴出,今天先发布客户端:

#pragma warning(disable: 4530)

#pragma warning(disable: 4786)

#include <iostream>

#include <ctime>

#include <cassert>

using namespace std;

#include <winsock2.h>

#include <windows.h>

static char * get_error_msg()

{

static char msg_buf[1024];

FormatMessage(

FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,

NULL,

GetLastError(),

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language

msg_buf,

1023,

NULL

);

return msg_buf;

}

void time_internet_to_local(void *recv_buf) //接到的数据转换为本地时间

{

assert(recv_buf);

char p[4], *precv = ((char *)recv_buf) + 3;

for(int i=0; i<4; i++)

p[i] = *precv--;

*(long *)p -= 2208988800;

SYSTEMTIME st;

tm * ptm = gmtime((time_t *)p);

st.wYear = ptm->tm_year + 1900;

st.wMonth = ptm->tm_mon + 1;

st.wDay = ptm->tm_mday;

st.wHour = ptm->tm_hour;

st.wMinute = ptm->tm_min;

st.wSecond = ptm->tm_sec;

st.wMilliseconds = 0;

SetSystemTime(&st);

}

void print_time(void *recv_buf)//打印接到的数据

{

assert(recv_buf);

char p[4], *precv = ((char *)recv_buf) + 3;

for(int i=0; i<4; i++)

p[i] = *precv--;

*(long *)p -= 2208988800;

char buf[15];

strftime(buf, 80, "%Y-%m-%d %H:%M:%S", localtime((time_t *)p));

cout << buf << endl;

}

void tcp(void *ip)//RFC868 PORT 37 TCP协议

{

struct sockaddr_in server;

server.sin_family = AF_INET;

server.sin_port = htons(37);

server.sin_addr.s_addr = inet_addr((char *)ip) ;

SOCKET s = socket(AF_INET, SOCK_STREAM, 0);

if(s == INVALID_SOCKET)

cout << __LINE__<<" socket error : " << WSAGetLastError() << endl;

int ret = connect(s, (struct sockaddr*)&server, sizeof(server));

if(ret == SOCKET_ERROR)

cout << __LINE__ << get_error_msg() << endl;

else

{

char xx[4];

ret = recv(s, xx, 4, 0);

if(ret == SOCKET_ERROR)

cout << __LINE__ << get_error_msg() << endl;

else

{

print_time(xx);

//time_internet_to_local(xx);设定本地时间 最好加一个判断网络延时

}

if(shutdown(s, SD_RECEIVE) == SOCKET_ERROR)

cout << __LINE__ << get_error_msg() << endl;

}

closesocket(s);

}

void udp(void *ip) //RFC868 PORT 37 UDP

{

struct sockaddr_in server;

server.sin_family = AF_INET;

server.sin_port = htons(37);

server.sin_addr.s_addr = inet_addr((char *)ip) ;

SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);

if(s == INVALID_SOCKET)

{

cout << __LINE__ << get_error_msg() << endl;

}

int ret, c_len = sizeof(server);

char r_buf[4];

ret = sendto(s, r_buf, 0, 0, (struct sockaddr *)&server, sizeof(server));

if(ret == SOCKET_ERROR)

cout << __LINE__ << get_error_msg() << endl;

FD_SET read_set;

timeval tv = {3, 0}; //tv.tv_sec = 0, tv.tv_usec = 100000; 0.1s

FD_ZERO(&read_set);

FD_SET(s, &read_set);

ret = select(0, &read_set, NULL, NULL, &tv);

if(ret == SOCKET_ERROR)

{

cout << __LINE__ << get_error_msg() << endl;

}

else

if(FD_ISSET(s, &read_set))

{

ret = recvfrom(s, r_buf, 4, 0, (struct sockaddr *)&server, &c_len);

if(ret == SOCKET_ERROR)

cout << __LINE__ << get_error_msg() << endl;

else

{

print_time(r_buf);

}

}

closesocket(s);

}

int main(int argc, char *argv[])

{

WORD wVersionRequested;

WSADATA wsaData;

wVersionRequested = MAKEWORD(2, 2);

WSAStartup(wVersionRequested, &wsaData);

char *ipcn = "159.226.154.16";//国家授时中心

char *iphk = "210.0.235.14";//香港天文台授时中心

time_t now;

char buf[15] = {0};

now = time(NULL);

strftime(buf, 80, "%Y-%m-%d %H:%M:%S", localtime(&now));

cout << "TCP 连接国家授时中心 " << endl << "本地时间 " << buf << endl << "远程时间 ";

tcp(ipcn);

now = time(NULL);

strftime(buf, 80, "%Y-%m-%d %H:%M:%S", localtime(&now));

cout << "UDP 连接香港天文台授时中心 " << endl << "本地时间 " << buf << endl << "远程时间 ";

udp(iphk);

WSACleanup();

return 0;

}

RFC 868

Network Working Group J. Postel - ISI

Request for Comments: 868 K. Harrenstien - SRI

May 1983

Time Protocol

This RFC specifies a standard for the ARPA Internet community. Hosts on

the ARPA Internet that choose to implement a Time Protocol are expected

to adopt and implement this standard.

This protocol provides a site-independent, machine readable date and

time. The Time service sends back to the originating source the time in

seconds since midnight on January first 1900.

One motivation arises from the fact that not all systems have a

date/time clock, and all are subject to occasional human or machine

error. The use of time-servers makes it possible to quickly confirm or

correct a system's idea of the time, by making a brief poll of several

independent sites on the network.

This protocol may be used either above the Transmission Control Protocol

(TCP) or above the User Datagram Protocol (UDP).

When used via TCP the time service works as follows:

S: Listen on port 37 (45 octal).

U: Connect to port 37.

S: Send the time as a 32 bit binary number.

U: Receive the time.

U: Close the connection.

S: Close the connection.

The server listens for a connection on port 37. When the connection

is established, the server returns a 32-bit time value and closes the

connection. If the server is unable to determine the time at its

site, it should either refuse the connection or close it without

sending anything.

RFC 868 May 1983

Time Protocol

When used via UDP the time service works as follows:

S: Listen on port 37 (45 octal).

U: Send an empty datagram to port 37.

S: Receive the empty datagram.

S: Send a datagram containing the time as a 32 bit binary number.

U: Receive the time datagram.

The server listens for a datagram on port 37. When a datagram

arrives, the server returns a datagram containing the 32-bit time

value. If the server is unable to determine the time at its site, it

should discard the arriving datagram and make no reply.

The Time

The time is the number of seconds since 00:00 (midnight) 1 January 1900

GMT, such that the time 1 is 12:00:01 am on 1 January 1900 GMT; this

base will serve until the year 2036.

For example:

the time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT,

2,398,291,200 corresponds to 00:00 1 Jan 1976 GMT,

2,524,521,600 corresponds to 00:00 1 Jan 1980 GMT,

2,629,584,000 corresponds to 00:00 1 May 1983 GMT,

and -1,297,728,000 corresponds to 00:00 17 Nov 1858 GMT.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有