网络游戏中的(低精度)时间同步

对于网络游戏来说,从物体的移动、攻击到最基础的计时等等,都需要客户端与服务器保持时间的相对一致,那么服务器与客户端同步便是一个必须要解决的问题。通常,网络游戏都会利用心跳来进行同步,那么当客户端并不需要如此精度的同步时,有没有其他方法呢?这里主要讨论低精度的时间同步(精确到秒)。

工作中接触过3种简单的时间同步方法:

首先,定义时间同步类

/// 32位操作系统
typedef unsigned int64_t QWORD;
typedef unsigned long    DWORD;

class TimeSynchronize()
{
public:
    void ServerTimeSync(QWORD ServerTime);
    QWORD GetLocalTime();

private:
    QWORD initServerTime;
    QWORD initClientTime;
    DWORD initClientTimeFromStartup;
};

/// 服务器下发同步消息
void TimeSynchronize::ServerTimeSync(unsigned int64_t serverTime)
{
    initClientTime = time(NULL);
    initServerTime = serverTime;
    initClientTimeFromStartup = timeGetTime();
}

1.当客户端启动的时候,服务器向客户端下发服务器当前的时间,当客户端需要获取当前时间时,只需用校正过的时间加上本地时间即可。

DWORD TimeSynchronize::GetLocalTime()
{
    return initServerTime  - initClientTime + time(NULL);   ///< initServerTime  - initClientTime为了消除客户端与服务器的时间误差
}

看到这里,细心的同学要笑了,这种做法修改本地的系统时间,不就修改了该函数的返回值么。确实,接口中只要取用了本地时间,便将修改本地时间的风险带入了接口。

2.服务器定时向客户端发送同步消息,就是所谓的心跳机制,类似TCP中的心跳,服务器定时发送一个自定义的结构体(心跳包或心跳帧),让对方知道自己“在线”。 以确保链接的有效性。当服务器超过一定时间没有收到来自客户端的回复,则当做玩家掉线,服务器关闭socket链接。不同的游戏也会根据游戏类型的不同,根据自己的需要设计心跳机制,间隔从几十ms到几s不等。

那么当客户端在大部分时间中并不需要高精度的时间同步时,有没有其他办法以降低对服务器性能的消耗?

3.利用timeGetTime接口,与同步时获取的服务器时间模拟当前时间。

//  timeGetTime:函数以毫秒计的系统时间。该时间为从系统开启算起所经过的时间。
//  DWORD timeGetTime(VOID);
//  参数:无参数。
//  返回值:以毫秒值返回系统时间。
DWORD TimeSynchronize::GetLocalTime()
{
    return initServerTime + timeGetTime() - initClientTimeFromStartup + initServerTime  - initClientTime;
}

可以看到timeGetTime的返回值精度为(ms),对于精度要求为(s)级的应用来说,已然够用了。

当然利用timeGetTime()要注意返回值为32位,取值范围为0~2^32,约为49.71天,要避免溢出。如果服务端利用该接口,又不便于重启服务器,建议利用精度更高的接口,如:QueryPerformanceFrequency(),QueryPerformanceCounter()。

时间: 2024-10-14 10:17:40

网络游戏中的(低精度)时间同步的相关文章

ORACLE 中NUMBER 类型 低精度转换成高精度

例如: 表User中有一个字段 salary  Number(10,3), 如果想把字段salary的类型提高精度到salary  Number(10,6),保留六位小数, 解决办法:1,ALTER TABEL USER MODIFY SALARY NUMBER(13,6); 解释:number类型刚开始是,长度10位,3位小数,如果想增加3位小数,对应的长度也必须增加,否则无法修改.所以NUMBER(13,6);这样就可以提高精度了, ORACLE 中NUMBER 类型 低精度转换成高精度

帧同步在竞技类网络游戏中的应用

帧同步在竞技类网络游戏中的应用 帧同步在网上可以搜的资料比较少,关于游戏的更是没有,不过,实现的原理也比较简单,最近几天就写了份关于帧同步的文档,当作给同事扫扫盲,顺便也在这里发发,可以给其他人参考参考     --竞技类网络游戏设计方案   一.        前言 帧同步,根据wiki百科的定义是,一种对同步源进行像素级同步显示的处理技术,对于网络上的多个接入者,一个信号将会通过主机同步发送给其他人,并同步显示在各个终端上.同步信号可以是每帧的像素数据,也可以是影响数据变化的关键事件信息.

int类型被强制转换成较低精度的byte类型

公司的项目上线之前会进行代码合规性检查,其中很容易违反的一个规则就是“不要把原始类型转换成较低的精度”,实际开发的过程中,很多方法在处理数据时,尤其在做移位操作的时候,难免要把int类型转换成byte类型,这时候就不可避免得出现原始类型转换成较低精度的情况,没有什么简便的方法,只能通过调用ByteArrayOutputStream,DataOutputStream 来处理.把处理过程封装到一个函数中.然后在进行类型转化的时候调用函数.处理函数如下: public byte intToButeAr

ambari过程中要求各个节点时间同步

设置时间同步 控制节点机器 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #设置时区为北京时间,这里为上海,因为centos里面只有上海... ntpdate us.pool.ntp.org #时间同步 加入定时计划任务,每隔10分钟同步一下时钟 crontab -e 把下面的内容粘贴进去保存即可 0-59/10 * * * * /usr/sbin/ntpdate us.pool.ntp.org | logger -t NTP slave

js中浮点数的精度问题

JS中浮点数的精度问题 value = parseFloat((value.toFixed(2))).toLocaleString(); //大于1的数值没有问题,小于1的,个位数的0会丢失,如:0.1,转换之后:.1 function accAdd(arg1,arg2){ var r1,r2,m; try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} try{r2=arg2.toString().split("

ACM中的浮点数精度处理

在ACM中,精度问题非常常见.其中计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,让你debug半天都找不到错误出在哪. 1.浮点数为啥会有精度问题: 浮点数(以C/C++为准),一般用的较多的是float, double. 占字节数 数值范围 十进制精度位数 float 4 -3.4e-38-3.4e38 6~7 double 8 -1.7e-308-1.7e308 14~15 如果内存不

网络游戏中的主循环

引言: 网络游戏作为一种复杂度较高的软件,从其设计角度还是有一些共性的,比方说几乎所有的网游都会有一个主循环.由于游戏需要根据输入.游戏内状态的改变来不间断地更新游戏画面,所以游戏的主循环往往看起来像一个"死循环",那么这个"死循环"是如何工作的? 主循环主要做什么? 1.处理游戏逻辑(输入.AI.事件处理) 2.执行渲染操作(更新游戏画面) 注:对于事件处理,可以归入游戏逻辑一类中,但是在实际中为了处理的方便,往往将事件处理独立出来.(windows环境下) 一个

android中导入低版本project可能会遇到的编译问题(转自: [email&#160;protected])

使用高版本的SDK后再导入以前用低版本的project时,会遇到一些兼容性的问题. (1)Unable to resolve target 'android-5' 因为本机中现在使用的是2.2的SDK,API的版本是8:而导入的工程使用的是2.0开发的,其API版本是5. 需要将default.properties中的target=android-5改为target=android-8就好了. 但要注意,也要同步将AndroidManifest.xml中的<uses-sdk android:mi

spark streaming kafka1.4.1中的低阶api createDirectStream使用总结

转载:http://blog.csdn.net/ligt0610/article/details/47311771 由于目前每天需要从kafka中消费20亿条左右的消息,集群压力有点大,会导致job不同程度的异常退出.原来使用spark1.1.0版本中的createStream函数,但是在数据处理速度跟不上数据消费速度且job异常退出的情况下,可能造成大量的数据丢失.幸好,Spark后续版本对这一情况有了很大的改进,1.2版本加入WAL特性,但是性能应该会受到一些影响(本人未测试),1.3版本可