欢迎光临散文网 会员登陆 & 注册

联机游戏网络相关内容总结

2018-10-15 17:59 作者:皮皮关做游戏  | 我要投稿

作者:ProcessCA


本篇难度:★★★☆☆

(请注意,本文是一次技术总结,对网络不太熟悉的童鞋食用前请做好心理准备)


大渣好。

最近整理了一下网络游戏相关的技术,主要由三个部分构成:

1.网络传输协议:HTTP,UDP,TCP

2.同步策略:状态同步,帧同步,还有介于两者之间的同步策略

3.序列化工具:Protobuf,自制工具

正是以上技术构成了网络游戏开发的基础,水平有限,欢迎指正。


在宏观的网络世界中,不同地区的电脑依靠互联网设施与自带的网卡就可以进行网络通信,因为互联网本身就由一系列协议组成,在OSI(开放系统互联)模型的基础上,TCP/IP精简了不少东西,从7层模型变为4层模型,遵循这套协议的机器就可以实现网络通信。

来自网络

网络传输协议

游戏开发中我们只需要关注TCP/IP协议族中的应用层传输层

应用层提供了许多协议支持不同应用的开发,比如通过浏览器访问知乎用到了HTTPS协议,HTTPS是在HTTP基础上加入了一层加密的协议。

在卡牌,跑酷这种弱交互游戏中,一般没有实时对战,偶尔请求服务器进行抽卡或者查看排行榜。可以借助应用层的HTTP协议进行通信,HTTP协议基于请求-相应模型,较为简单,方便调试。

举个HTTP协议在卡牌游戏中抽卡的例子:

1.客户端向服务器发送Get或Post请求。

2.服务器接受到消息后进行抽卡逻辑。

3.服务器向客户端发送请求的相应。

4.客户端接收到回应消息后进行显示操作。

然后就抽中了:

说得好像SSR很容易抽似的

如果涉及到了实时交互的游戏,如RPG,MMO这种往往会使用传输层的TCP,UDP协议保证实时交互。具体选择什么协议得看具体的项目,对传输带宽与速度有严格要求推荐使用UDP,否则推荐使用TCP确保可靠性,降低开发成本。两种协议搭配实现游戏中的不同网络模块也是十分常见的解决方案。

以下是两种协议的对比:

图片来自:https://blog.csdn.net/hai_chao/article/details/79626161

同步策略

同步策略可分为状态同步,帧同步与介于两者之间的同步,关于状态同步与帧同步,网上有大量的文章介绍,大家也有不同的理解。下面说说我的看法:

状态同步:从字面意思上理解就是客户端通过服务器同步自己的状态。这个状态指的是具体的数值。比如向服务器发送:我的旋转角度改为(0, 90, 0),我的坐标更新为(100, 100, 0),这个过程服务器可以不进行逻辑判断。

但是基于这种纯粹的方式无法直接检测客户端发送数据的真实性,为了防止严重的作弊,可以对每次客户端发送的数据进行范围限制,确保结果在一个可接受范围内。

在利用UnityNetworking进行原型开发时用到的[SyncVar]特性,它的作用就是在网络中同步指定字段的值。不得不说利用这种策略去堆叠游戏的原型的时候开发效率非常高。


帧同步:指每个客户端只同步自己的操作。操作可以是:Q, W, E, R这种按键,也可以是鼠标滑动后产生的向量。操作上传给服务器后,服务器直接转发给其他的客户端,在每个客户端上进行逻辑运算,通过确保不同客户端在相同的时间接受输入,在相同时间得到相同的结果。

关于确保帧同步的准确性有两种常用的方式:LockStep(锁步)与乐观的帧同步。

为了确保比赛结果的准确性,帧同步服务器上可以运行一套客户端参与运算,结果以其为准。但是一个无法解决的问题是:逻辑运算变成了客户端的事,我们完全可以通过修改客户端本身实现作弊,比如开启全图视野,这种外挂服务器是无法预料的。

一般对于这种情况会依赖一些其他的工具验证客户端程序的完整性,内存监控等方式弥补这一点缺陷。但是无法根本上杜绝作弊,所以我们会在FPS,RTS这些应用帧同步比较广泛的游戏类型中看到各种全图挂,透视挂层出不穷。

但是对于格斗游戏,采取帧同步算是最正确的做法。

格斗游戏对延迟敏感,一局游戏的所有信息对双方的完全透明。所以基本上联机格斗游戏都会选择帧同步。


基于两者之间:现实的网络游戏中情况比较复杂,要防止客户端作弊,最简单有效的办法是把游戏的大部分逻辑放在服务器上面。这时就不是客户端说了算,客户端只能发送一些操作指令比如:我要向左转90度,跑向一个目标点。

服务器收后客户端的指令后进行逻辑运算,然后把结果同步给所有客户端。这样的好处显而易见,客户端没有办法直接修改数据,基本上防止了作弊。

但是缺点也明显:就是服务器压力大,流量消耗大。特别是针对大型网游,会采取一系列优化措施保障服务器的稳定。

比如魔兽世界主要采用这种方式进行同步:

序列化工具

在这里要说的一点是关于序列化工具首推的是Protobuf,因为其序列化效率高,易用,跨语言的特性使得protobuf在游戏开发中有着十分广泛的应用。如果有能力自己实现一套序列化工具也是可以的,用C#的API就可以做到:

using System.Net;using System.Net.Sockets;using System.IO;using System.Runtime.Serialization.Formatters.Binary;using System.Text;/// <summary>/// 网络工具类 <see langword="static"/>/// </summary>public static class NetworkUtils{

    //序列化:obj -> byte[]

    public static byte[] Serialize(object obj)

    {

        //对象必须被标记为Serializable

        if (obj == null || !obj.GetType().IsSerializable)

            return null;

        BinaryFormatter formatter = new BinaryFormatter();

        using (MemoryStream stream = new MemoryStream())

        {

            formatter.Serialize(stream, obj);

            byte[] data = stream.ToArray();

            return data;

        }

    }

 

    //反序列化:byte[] -> obj

    public static T Deserialize<T>(byte[] data) where T : class

    {

        //T必须是可序列化的类型

        if (data == null || !typeof(T).IsSerializable)

            return null;

        BinaryFormatter formatter = new BinaryFormatter();

        using (MemoryStream stream = new MemoryStream(data))

        {

            object obj = formatter.Deserialize(stream);

            return obj as T;

        }

    }}

 

在之前的文章中有对Protobuf与C#序列化工具详细的介绍,这里放出连接:

游戏开发好帮手——Protobuf

OK,关于网络游戏的简单总结就到这里,希望本文对在游戏开发的道路上的你有所启发。

(顺便说一下,之后的文章还是会搭配具体的游戏。)


想系统学习游戏开发的童鞋,欢迎访问 http://levelpp.com/             

游戏开发搅基QQ群:869551769             

微信公众号:皮皮关

联机游戏网络相关内容总结的评论 (共 条)

分享到微博请遵守国家法律