android客户端与服务器时间同步

如何保障android客户端与服务器时间同步,不受用户更改系统时间的影响?

NTP协议

NTP原理如下:

系统时钟同步的工作过程如下:

Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该时间戳为10:00:00am(T1)。
当此NTP报文到达Device B时,Device B加上自己的时间戳,该时间戳为11:00:01am(T2)。
当此NTP报文离开Device B时,Device B再加上自己的时间戳,该时间戳为11:00:02am(T3)。
当Device A接收到该响应报文时,Device A的本地时间为10:00:03am(T4)。
至此,Device A已经拥有足够的信息来计算两个重要的参数:
NTP报文的往返时延Delay=(T4-T1)-(T3-T2)=2秒。
Device A相对Device B的时间差offset=((T2-T1)+(T3-T4))/2=1小时。

缺点分析

上述有几个地方可能会影响结果的准确度:

  • T4值的改变,也就是请求过程中如果改变本地时间,那么的出来结果肯定是错误的
  • 网络延迟的不确定性,如果请求网络的延迟时间和返回网络的延迟时间不相等的话,那么算出来的时间差也是不正确的,下面详细分析:
    上面的公式其实可以完善一下,加入两个变量,请求网络的延迟时间Y1和返回网络的延迟时间Y2,还有一个是时间差C,完整公式如下:
    公式1:T1+Y1+C=T2
    公式2:T3+Y2-C=T4
    公式1+公式2:Y1+Y2=(T4-T1)-(T3-T2),跟上面第一个公式一样
    公式1-公式2:C=((T2-T1)+(T3-T4)+(Y2-Y1))/2,当Y1和Y2延迟时间是一样的时候,就跟上面第二个公式一样了;当Y1和Y2延迟时间不一样的时候,那么得出来的结果是有误差的。

系统启动时间差

额,看了上面的方法,发现实际应用比较麻烦,因为用户随时可能更改系统时间,不可能每次都去校准一次。
下面说一个简单的方法:

  • 去服务器获取准确的时间,同时记录下当前的elapsedRealtime (SystemClock.elapsedRealtime() ,返回系统启动到现在的毫秒数,包含休眠时间)
  • 当要使用时间的时候,获取当前的elapsedRealtime 减去记录的elapsedRealtime 加上服务器获取到的时间戳,就是服务器的当前时间了

当然这里肯定是有误差的,主要是网络延迟带来的误差,对于时间精度要求不是很高的地方可以使用这个方法。因为elapsedRealtime 跟系统设置的时间无关,所以用户更改系统时间也不会影响。

参考:
Android客户端与服务器时间同步
Android中的SystemClock类

发布了216 篇原创文章 · 获赞 91 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/yu75567218/article/details/88579975