【网络游戏专题】时间同步装置

简介: 在网络游戏中,有一个最基本的需求是,如果让一个玩家的动作(比如行走)即时地、流畅地在其它的游戏地理位置相邻的玩家的屏幕上显现,如果是在局域网内,这个不是什么大不了的问题,但是如果游戏玩家是分散在Internet上的用户,由于网络的延时的影响,使得其成为项颇有难度的任务。

    在网络游戏中,有一个最基本的需求是,如果让一个玩家的动作(比如行走)即时地、流畅地在其它的游戏地理位置相邻的玩家的屏幕上显现,如果是在局域网内,这个不是什么大不了的问题,但是如果游戏玩家是分散在Internet上的用户,由于网络的延时的影响,使得其成为项颇有难度的任务。你只要想一下,玩家A发出的消息经过服务器中转到达玩家B时可能已经经过了几秒钟,那么A和B的游戏状态同步就是个问题了。关于解决状态同步问题的方案有一些,比如,预测拉扯技术、服务器验证同步技术、半服务器同步技术等,但是所有这些技术都需要依赖一个更基础的装置--时间同步装置,时间同步装置用于让所有的游戏客户端、游戏服务端都遵守同一个标准的时间,这样,由不同节点发出的消息上的时间戳才有统一的参考标准,这样我们才能比较准确的计算消息从A到B的延时。
    我采用这样的方式来实现时间同步装置:
(1)采用服务器(组)的时间为标准时间,这样所有客户端只要与服务器时钟同步即可。
(2)采用类似ping的技术来测量消息从客户端到服务端再回到客户端所花费的时间。
(3)通过一个系数可以调整消息上行速度和下行速度的比例,该比例默认为1,可以根据网络状况进行动态调整。
(4)可以每隔一段指定时间间隔自动同步一次,也支持强制手动调用同步。
    这基本上是时间同步装置的核心思想,在设计时,我考虑把它设计得更方便应用,详细讲解如下:
    首先,是定义时间同步装置的接口--IStandardTimeSynchronizer。


     ///   <summary>
    
///  IStandardTimeSynchronizer 时间同步装置,将服务器的时间作为标准时间参考系。
    
///  zhuweisky 2008.03.05
    
///   </summary>
     public   interface  IStandardTimeSynchronizer
    {
        
///   <summary>
        
///  SynchronizeSpanInSecs 自动同步服务器时间的时间间隔。
        
///   </summary>
         int  SynchronizeSpanInSecs {  get ; set ; }

        IPinger Pinger { 
set ; }

        
void  Initialize();

        
///   <summary>
        
///  GetCurrentStandardTime 获取经过本地预测的服务器当前标准时间
        
///   </summary>         
        DateTime GetCurrentStandardTime();

        
///   <summary>
        
///  Synchronize 与服务器进行时间同步,手动强制同步
        
///   </summary>
         void  Synchronize();

        
///   <summary>
        
///  ComputeLifeInMSecs 计算标记戳时的时刻到现在过了多少ms。(即,消息的当前年龄:))
        
///  注意,消息中的时间戳也是记录的当时(预测)的服务器标准时间。
        
///   </summary>
        
///   <param name="timeStamp"> 消息中的时间戳 </param>         
         double  ComputeLifeInMSecs(DateTime msgStampTime);
    }

    Initialize方法用于启动自动同步的定时器。IPinger接口用于发送ping消息到服务器,并带回服务器接收到ping消息的时间:

    ///   <summary>
    
///  IPinger 用于向服务器发送ping消息,用于计算消息延迟和预测服务器标准时间。
    
///  服务器对该ping消息的应答中必须包含服务器应答时刻的时间戳。
    
///  zhuweisky 2008.01.05
    
///   </summary>
     public   interface  IPinger
    {
        
///   <summary>
        
///  Ping 当该方法被调用时,客户端立即向服务器发送ping消息然后阻塞,直至收到服务器对该ping消息的应答后该函数才能返回。 
        
///   </summary>
         void  Ping( out  DateTime serverTimeStamp);
    }

    注意ping方法的注释:Ping方法被调用时,客户端立即向服务器发送ping消息然后阻塞,直至收到服务器对该ping消息的应答后该函数才能返回。为了避免额外的延迟,服务器必须非常迅速地应答Ping消息。关于服务端和客户端之间的高效通信,我使用通信框架ESFramework来解决。
    下面我们继续看时间同步装置的完整实现:

    public   class  StandardTimeSynchronizer :BaseCycleEngine  ,IStandardTimeSynchronizer
    {
        
///   <summary>
        
///  timeModifiedInMSecs 本地时间与服务器时间的差值(ms)。如果本地时间快,则取正值,否则取负值。
        
///   </summary>
         private   double  timeModifiedInMSecs  =   0 ;

        
///   <summary>
        
///  circleSpanInMSecs 从发出ping消息到收到服务器应答的总时间(ms)
        
///   </summary>
         private   double  circleSpanInMSecs  =   0 ;

        
///   <summary>
        
///  coefUpDownSpeed 消息下行的速度与上行速度的比例
        
///   </summary>
         private   double  coefDownUpSpeed  =   1 ;

        
#region  IStandardTimeSynchronizer 成员

        
#region  SynchronizeSpanInSecs
        
private   int  synchronizeSpanInSecs  =   10 ;
        
public   int  SynchronizeSpanInSecs
        {
            
get  {  return   base .DetectSpanInSecs; }
            
set  {  base .DetectSpanInSecs  =  value; }
        } 
        
#endregion        

        
#region  Pinger
        
private  IPinger pinger;
        
public  IPinger Pinger
        {
            
set  { pinger  =  value; }
        } 
        
#endregion

        
public   void  Initialize()
        {
            
base .Start();
        }

        
protected   override   bool  DoDetect()
        {
            Stopwatch stopwatch 
=  Stopwatch.StartNew();
            DateTime serverTimeStamp;
            
this .pinger.Ping( out  serverTimeStamp);
            
this .circleSpanInMSecs  =  stopwatch.ElapsedMilliseconds;

            DateTime pingBackTime 
=  DateTime.Now;

            
double  downCostInMSecs  =   this .circleSpanInMSecs  /  (coefDownUpSpeed  +   1 ); // 消息下行时间
            DateTime estimateServerActionTime  =  pingBackTime  -  TimeSpan.FromMilliseconds(downCostInMSecs); 

            TimeSpan timeModifiedSpan 
=  estimateServerActionTime  -  serverTimeStamp ;
            
this .timeModifiedInMSecs  =  timeModifiedSpan.TotalMilliseconds;

            
return   true ;
        }

        
public  DateTime GetCurrentStandardTime()
        {
            
return  DateTime.Now.AddMilliseconds( - this .timeModifiedInMSecs);
        }

        
public   void  Synchronize()
        {
            
this .DoDetect();
        }

        
public   double  ComputeLifeInMSecs(DateTime msgStampTime)
        {
            DateTime estimateServerCurTime 
=   this .GetCurrentStandardTime();
            TimeSpan span 
=  estimateServerCurTime  -  msgStampTime;

            
return  span.TotalMilliseconds;
        }
        
        
#endregion
    }

    BaseCycleEngine是一个循环工作的引擎,用于每隔一段时间执行一次DoDetect方法调用。

    上面介绍的是时间同步装置的客户端的实现,服务端的实现相当简单,只需要实现ESFramework中一个消息处理器接口并插入到框架即可。

    关于这种方案的缺陷是,如果消息上行速度和下行速度差异很大,而速度比例系数coefDownUpSpeed又设置不当的话,那么时间同步的误差就比较大,不知道你是否有更好的办法了?能够提高时间同步的精确度:)



























目录
相关文章
|
24天前
|
算法 网络协议 数据安全/隐私保护
NTP网络时间同步协议详解
NTP协议是互联网上用于同步计算机时间的标准,它利用分布式时间服务器网络,通过分层管理和本地路由算法确保时间的准确性。协议涉及时间偏差、延迟和差量三个概念,用于测量与参考时钟的同步状态。基本NTP数据包包含48字节,如头部和时间戳,关键字段如跳跃指示器(LI)、版本号(VN)、模式(Mode)、层次(Stratum)等影响同步过程。协议还包括时间戳以记录不同阶段的时间点。NTP认证可选,用于数据安全。
NTP网络时间同步协议详解
|
12月前
|
传感器 算法
m基于马尔科夫随机场和Gardner环的WSN网络时间同步matlab仿真
m基于马尔科夫随机场和Gardner环的WSN网络时间同步matlab仿真
95 0
|
传感器 算法
m无线传感器网络WSN的时间同步捕获算法matlab仿真,对比单步捕获法,双步捕获法以及锯齿波匹配捕获法
m无线传感器网络WSN的时间同步捕获算法matlab仿真,对比单步捕获法,双步捕获法以及锯齿波匹配捕获法
132 0
m无线传感器网络WSN的时间同步捕获算法matlab仿真,对比单步捕获法,双步捕获法以及锯齿波匹配捕获法
|
Linux Android开发
android命令行网络时间同步
一、简介 Android基于Linux平台的开源手机操作系统。 二、原理 既然是Linux,那就应该支持linux的各种命令行,高度的可配置,但实验发现Android是Google的一个高度阉割版的linux,很多命令都不支持,如rdate命令(网络同步时间命令)。
1610 0
|
9天前
|
网络协议 算法 Linux
【Linux】深入探索:Linux网络调试、追踪与优化
【Linux】深入探索:Linux网络调试、追踪与优化
|
3天前
|
Linux Shell 网络安全
网络安全中Dos和linux常用命令总结
本篇是对网安学习中,常用的命令做一个图文与命令示例,并对一些比较重要的dos和shell命令进行总结,方便自己后续学习进行查询,并希望能够给更多人有一个总结命令和了解命令的地方.
28 5
|
6天前
|
Ubuntu 网络协议 Linux