文档章节

在VC++中实现同步Internet时间

rise-worlds
 rise-worlds
发布于 2016/06/20 13:35
字数 1339
阅读 3
收藏 0

写作目的:(此段可跳过)
    同步Internet时间,即通过Internet的校时网站传来的数据校准本机时间。但是现在网络上查到的相关编程资料并不多,且其中多是VB和Delphi的代码,VC的代码我还没找到过。是这个东西太难了?应该不是;是太简单了?那也总该有人写吧。
   我认为,自己懂和让别人懂压根不是一回事,我写这篇文章,目的当然是后者。当然,理工科出身的河蚌不大可能像文科出身的河蚌那样修出光彩夺目的珍珠来,所以,行文有不妥之处,欢迎指正。
校时原理:
        互联网上有很多时间服务器能够提供准确的时间,我们通过连接到这样的服务器来获取时间值。这里向大家介绍一下服务器传来的数据格式先。数据一共四个字节(4 Byte),我们可以在接收数据后对它进行“重新组装”,把组装所得的值放在一个32位的整数里,这个值的意义是:自1900年1月1日0时0分0秒 至 服务器发送这个时间数据时 所经历的秒数。显然,任何一个时刻到1900年所经历的秒数是唯一的,因此,由服务器传来的时间数据即可推出现在的时间,然后用API函数调整系统的时间即可。

流程图如下:

设计目标:

        好了,我们的目标是:(没有蛀牙~)
    -_-!!
    常言说一图千言,我们还是看图吧:

程序的实现:

从技术角度来看,解决三个问题即可:
1. 通过网络通信从服务器获取时间数据。
2. 处理基于1900年的时间数据,转化为我们常见的时间形式。
3. 解决网络造成的延时问题。
下面分条讲述:
1.
通过网络通信从服务器获取时间数据。

至于接收数据,没什么可说的,这里用CSocket就可以了。

代码片断:

    CSocket sockClient;
    sockClient.Create();            //创建socket

//for debug
    m_info += "Connect server: " + strServer + " ";
    UpdateData(FALSE);
//for debug

    sockClient.Connect((LPCTSTR)strServer, 37); // strServer:时间服务器网址; 37:端口号

    DWORD dwTime = 0;                //用来存放服务器传来的标准时间数据
    unsigned char nTime[8];            //临时接收数据
    memset(nTime, 0, sizeof(nTime));

    sockClient.Receive(nTime, sizeof(nTime));    //接收服务器发送来得4个字节的数据
    sockClient.Close();                //关闭socket

//for debug
    m_info += "Connect shut down. ";
    UpdateData(FALSE);
//for debug

    dwTime += nTime[0] << 24;        //整合数据   
    dwTime += nTime[1] << 16;
    dwTime += nTime[2] << 8;
    dwTime += nTime[3];       

if(0 == dwTime)    return FALSE;

到此为止,服务器传来的时间数据经过“重新组装”已经正确放置到DWORD类型的变量 dwTime 里面了。下面我们接着对其进行必要的处理。


2.
处理基于1900年的时间数据,转化为我们常见的时间形式。

在前面我们提到,时间数据已经正确放置到变量 dwTime 里面了。那么,怎样由它得到现在的时间呢?

微软已经给我们提供了一个很好用的时间类:CTime。不过,MFC的CTime类的时间起点是基于1970年的,而dwTime 里面的秒数是从1900年计时的。

用CTime?无法由 dwTime 中的数据直接构造CTime类的对象。

用C的函数库?我尝试了多次,N次碰壁。

说起最终敲定的实现方法,其实很简单- 改变计时基准。

时间转换的方法如下:

1.  用 COleDateTime 和 COleDateTimeSpan 算出1900年1月1日0时0分0秒 到 1970年1月1日0时0分0秒 所经历的秒数 dwSec00to70。

2. 从 dwTime 中减去 dwSec00to70。此后,dwTime 所代表的就是自1970年1月1日0时0分0秒以来逝去的秒数――显然,dwTime 已经被我们转变为基于1970年的时间值了,这回可以用CTime进行处理了。

怎么样?不复杂吧。(想起了近几天屡试屡败的经历和查阅的N多资料,自己吐血先)
代码片断:

//服务器传来的数据是自从1900年以来的秒数
//取得 1900~1970 的时间差(以秒数计算) ,放在dwSpan里面
    COleDateTime t00( 1900, 1, 1, 0, 0, 0 ); // 1900.1.1 00:00:00
    COleDateTime t70( 1970, 1, 1, 0, 0, 0 ); // 1970.1.1 00:00:00

    COleDateTimeSpan ts70to00 = t70 - t00;
    DWORD dwSpan = (DWORD)ts70to00.GetTotalSeconds();
    ASSERT( dwSpan == 2208988800L );

//把时间变为基于1970年的,便于用CTime处理
    dwTime -= dwSpan;       
//考虑网络延迟因素
    dwTime += dwDely;
//构造当前时间的CTime对象
    CTime timeNow = (CTime)dwTime;

//for debug
    m_info += timeNow.Format("%Y.%m.%d  %H:%M:%S  ");
    UpdateData(FALSE);
//for debug

3. 解决网络造成的延时问题。

    在从服务器获取时间数据时,由于网络本身的不稳定性,一般会有时间上的延迟(几秒以内),这样一来,从服务器接收到的数据总早于的真实时间。解决的办法是设定一个计时器,计算出本机从开始网络连接到接收完数据所耗费的时间dwDelay,然后加到 dwTime 上进行补偿。这样一来误差就可以控制在1秒以内(如果你不用你的爱机控制导弹飞行或者航天发射,应该够用了),详见源码。

本文转载自:http://www.cnblogs.com/flying_bat/archive/2007/10/11/921033.html

共有 人打赏支持
rise-worlds

rise-worlds

粉丝 2
博文 1755
码字总数 0
作品 0
深圳
程序员
私信 提问
用vc++做基于概率算法的算法动态演示系统

1、内容提要: 设计并实现典型算法的动态模拟演示,如:数值概率计算、在一个数组中找到“a”的Las Vegas算法与Monte Carlo算法、快速排序算法、验证两个数组的乘积是否正确、商旅问题等的动...

卡卡110120
2014/05/08
114
2
用ICE开发分布式程序

ICE是ZeroC公司开发的一款高效的开源中间件平台,全称是Internet Communications Engine。 它的主要设计目标是: • 提供适用于异种环境的面向对象中间件平台。 • 提供一组完整的特性,支持...

Waiting4you
2009/06/08
4.5K
1
host、dig、nslookup 查询DNS命令

host 命令: 一般格式: host 域名 host -a 域名 常用选项: -a:相当于"-v -t any"。 -t type:指定要查询的记录类型。默认查询A、AAAA、MX记录。 -v:详细方式输出。 [root@BJ-IDC-NTP-002...

zhailibao
2015/09/28
459
0
vc升级失败恢复快照后数据不一致问题

第一次故障现象: 下午192.168.146.1 vc5.5升级6.0失败后回滚。Vcenter、DB和SSO均做的是带内存的快照。当时检查恢复完能连上vc和web client。当天晚上发现vc连接中断,第二天早上再次出现中...

xjsunjie
2017/10/24
0
0
Quartz在Spring中的集群

环境:多个tomcat(可以在一台机器,也可以在多台机器),同一个数据库 每台机器必须保证时间同步,否则会出现离奇且不可预知的行为,有几种简单的方法来保证时钟何持同步,而且也没有理由不...

tmac1yan
2016/01/21
49
0

没有更多内容

加载失败,请刷新页面

加载更多

nginx rails 详细站点配置入门教程

Ruby on Rails 是一个用于开发数据库驱动的网络应用程序的完整框架。Rails基于MVC(模型- 视图- 控制器)设计模式。从视图中的Ajax应用,到控制器中的访问请求和反馈,到封装数据库的模型,R...

xiangyunyan
49分钟前
3
0
Shiro

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

嘿嘿嘿IT
53分钟前
1
0
Flutter 之 Dart语言基础详解 上篇

经过了一个星期的React Native的学习和了解,感觉还是Flutter的优势会更高一些,而且从学习成本来说感觉做安卓的同学学习flutter会相对低一点,门槛会低很多。 当然dart的基础笔者还是从其他...

林-师傅等等我
今天
5
0
Java NIO问题总结

问题1:IO事件在被处理之前,selector.select()方法依然能够返回该事件。即如果在一个线程A中进行selector.select(),而将selector.selectedKeys()中的SelectionKey交由业务线程池去处理,则...

月下狼
今天
5
0
ehcache

简单介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。Ehcache是一种广泛使用的开 源Java分布式缓存。主要面向通用缓存,Java EE和轻量...

大笨象会跳舞吧
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部