在Unity框架设计中与游戏服务器对接的网络框架也是非常重要的一个模块,本文給大家分享如何来基于Unity来设计一个网络框架, 主要的讲解以下几个点:
(1) TCP半包粘包, 长连接与短连接, IO阻塞;
(2) Tcp Socket与UDP Socket 的技术方案;
(3) Unity的序列化与反序列化技术方案;
(4) TCP的封包与拆包;
(5) 基于http的短连接技术方案;
(6) Unity 网络框架设计与实现原理;
对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。
TCP半包粘包, 长连接与短连接, IO阻塞
TCP 是可靠的网络传送协议,网络传输底层每发送一个TCP数据包,就要等对方确认,收到确认消息以后才能发下一个TCP数据包。当我们在应用层发送一个应用层的数据包的时候,TCP网络底层可能会把这个应用层的数据包分成若干”TCP数据包”,通过网络底层发出去。那么这里就会有一个问题,应用层发的数据包有可能被拆散成几个”TCP数据包”发出去,我们在另外一端接收的时候,可能要把这些拆散的包组合起来。这个就是”半包”。底层有可能把两个应用层的数据包分到一个”TCP数据包”发过去,接收到后,一部分是属于上一个应用层的数据包,一部分属于下一个应用层的数据包,这个叫做”粘包”。
Tcp Socket与UDP Socket 的技术方案
了解完网络的一些基本概念以后,接下来看下使用TCP/UDP Socket用哪些技术方案。Unity其实是作为网络的客户端,而客户端只要去连接服务端与服务器通讯就可以了,不用像服户端同时处理N个客户端的数据传送。所以客户端Socket非常的简单。Unity客户端的Socket我们用哪个插件呢?其实这种完全不需要用什么插件,直接使用OS为我们提供的Socket的相关API就可以了。
TCP Socket 面向连接的,使用流程如下:
Unity的序列化与反序列化技术方案
网络发送的都是数据字节流,Unity与服务端通讯要把要发送的数据对象变成二进制字节流,然后通过网络传送出去,收到字节流以后,又要重建回数据对象,完成数据发送。数据对象变成二进制字节流这个过程叫序列化,把二进制字节流转回数据对象叫反序列化。
序列化/反序列化目前主要有两个打的方向:一个是二进制序列化,一个是文本序列化;
二进制序列化/反序列化:基于二进制的bit,通过用户商量的协议来把数据对象变成二进制bit数据流,反序列化的时候根据用户协议,来把bit数据流变成数据对象。
文本序列化的解决方案: json, xml等;
二进制序列化/反序列化解决方案: protobuf;
TCP的封包与拆包
上面讲解了,应用层的数据包有可能被拆分成若干”TCP数据包”,还有可能两个应用层的数据包连在一起在一个”TCP数据包”中。为了收数据的时候能完整正确的收到应用层的数据包,我们必须要把两个应用层的数据报之间做好分隔标记,当我们收到数据以后就可以根据分隔标记来决定哪些数据是哪个包的。目前有两种做法:
(1) 大小+数据内容+校验码模式;[size][数据body][校验], 游戏开发中经常会使用这种方式来做封包, 收数据的时候,根据大小来将数据包完整的组合出来。WebSocket也是采用的这种方式。
(2) 特定的分割符模式: 123456\r\n67890, Html采用特定的分割符号来拆分数据内容。
基于http的短连接技术方案
短连接,前面个讲过的,用完就断开连接,下次要用的时候再重新的连接。短连接是使用TCP Socket策略,而这种策略最常用的就是http(基于TCP Socket+http超文本传输协议)。
Unity网络框架中也要使用http,主要是和服务器对接基于http通讯以及资源服务器的下载等需求。Unity作为客户端,要使用http,都已经封装好了UnityWebRequest,同时UnityWebRequest是多线程模式,可以同时并发N个请求。
Unity 网络框架设计与实现原理
铺垫了这么多,我们直接来上Unity网络框架的架构设计结构图,供大家参考。
这里接收数据的时候,采用多线程来做,收到数据后,进行拆包与反序列化,得到数据对象后,放事件队列,游戏主线程从事件队列里面获取网络事件,然后进行处理。发送数据出去的时候,我们在游戏主线程调用异步的网络Send函数,避免IO阻塞。注意好这些点,就可以设计出一个很好的网络框架。