Unity网络游戏实战读书笔记(三、四章粘包分包,大小端,发送完整的数据,以及ByteArray构造)


项目代码:在这


第三章

客户端:定义了NetManager。负责Socket连接,发送,接收。具体接收信息操作将会根据MsgName委托给Main类中的函数操作
服务端:同样MainClass负责Socket的功能,并将消息具体操作给MsgHandler执行。
客户端,在发送List(获取玩家信息时)。客户端加个Enter和List一块发送,导致粘包。书中没有处理,这里可以延迟一点时间发送List消息
这里只实现了进入Enter、Move和Leave。书中攻击、伤害和死亡协议未实现


第四章

  • 操作系统层面Socket有发送缓冲区和接收缓冲区、用户的Send和Receive只是从缓冲区中存取,由于缓冲区的情况,所以很容易出现粘包和缺包的情况。

粘包

  • 解决方案:
  1. 长度信息法、发送每一个消息前加上消息的字节长度、这里长度一般可以使用16bit(2个字节)和32bit(4个字节)的整数来表示
  2. 固定长度、每次发送消息均为固定长度
  3. 结束符、发送消息后缀均为特殊自定义符号
  • 文中利用了长度信息法来解决粘包的情况
  1. 服务器会将发送的消息体完全的广播给客户端,并且选用Int16作为消息长度信息放在消息头部
  2. 客户端首先定义recvBuffCount标识当前recvBuff有多少字节数据,在接收到数据时,将会把此次数据长度加到recvBuffCount上。然后调用OnReceiveByteData处理数据。
  3. 首先判断 recvBuffCount是否小于2,如果小于2说明recvBuff没有完整的消息长度信息,直接返回。如果有利用BitConverter.ToInt16(recvBuff, 0);取出消息长度信息bodyLength。
  4. 然后判断recvBuff中是否大于等于2+bodyLength。没有说明这条消息不完整。否则从index=2,取出bodyLength长度。
  5. 最后更新recvBuff和recvBuffCount ,也就是recvBuffCount -=2+bodyLength。然后将recvBuff前2+bodyLength个字节数据去除。这里使用了Array.Copy进行了前移。这里可以想到ET中的CircularBuffer。CircularBuffer使用了一个环形的循环。就不用像这里进行数组拷贝了。
  6. 这里客户端在RecvCallback使用了System.Threading.Thread.Sleep(10000);阻塞了子线程,来模拟客户端粘包的情况。下图可以看到服务端接收了3条消息。客户端会先显示123,然后等待10s后开始接收并解析剩余的消息。

大小端

个人理解:大端:高尾端,小端:低尾端。顺序是低地址->高地址
解决方案: 统一使用小端

  1. 在进行BitConverter.GetBytes将会判断是否为小端,如果不是小端!BitConverter.IsLittleEndian。利用Reverse反转
  2. 取出消息前两位之前用了BitConverter.ToInt16函数。这个函数内部做了一些大小端的处理。但是我们可以仿照这个函数手动来处理。Int16 bodyLength = (short)((recvBuff[1] << 8) | (recvBuff[0]));
  3. 解释一下上面的,(星pbyte)指向缓冲区第一个字节,星(pbyte+1)指向缓冲区第二个字节。以小端为例,星(pbyte+1)<<8,左移8位也就是乘2的8次幂。然后 | (星pbyte)也就是相加(自己理解0 | 1 = 1是不是相加)

如何发送完整的数据

  • 在发送数据时,定义ByteArray这个类型包括,此次发送的起始索引readIdx=0,和数据长度等然后入队列writeQue。然后判断writeQue队列中是否只有一个只有一个那么将直接发送。否则不发送,此处调用的方法时BeginSend
  • 然后在SendCallback回调中,从队列取出第一个firstBa,根据实际发送字节长度更新firstBa的readIdx。如果剩余字节数firstBa.Length == 0,那么说明当前这条信息完整发送。将会这个ByteArray推出,然后取出下一个ByteArray。然后判断此时的firstBa是否为null(此时的firstBa可能是第二个ByteArray,也可能是第一个没有发送完整的),不为null将会继续发送
  • 这里因为BeginSend,SendCallback执行在不同的线程中,加入猛点Send。这是可能SendCallback正在执行,又开了一个新线程执行SendCallback。这时将会同时操作writeQue的入队列或者出队列造成资源的竞争。所以这里采用lock进行了加锁。可以看到加锁光写就很不方便。所以ET采用了多进程单线程。

  • ByteArray这个结构包含了扩容功能,并且每次需要翻倍时候,将会扩容至原来的2倍,例如1、2、4、8…,还包含对数据的读写,Write操作将会自动判断写入时剩余空间是否足够,不够将会自动扩容,Read操作时,将会根据条件判断是否满足数据前移动操作(也就是Array.Copy)。文中是数据小于8将会进行前移操作。这里复杂度为O(8)。并且提供了读取Int16和Int32长度信息的操作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Unity3D网络游戏实战PDF》是一本非常重要的Unity3D开发书籍,它着重介绍了Unity3D游戏开发的网络部分。本书包含了网络游戏的核心概念、原理及实现方法,深入剖析了网络游戏的架构设计模式、游戏性能优化、安全防护等方面内容,并提供了实际的案例分析和设计思路,是网络游戏开发者的必备指南。 本书主要包括了以下内容:网络游戏的基础知识,如网络通信、协议、数据传输、数据整合等;Unity3D网络游戏的基本架构设计,如服务器端和客户端的架构设计、消息通信机制等;Unity3D游戏性能优化技巧,如消息压缩、消息缓存、负载均衡等;网络游戏的安全防护策略,如加密算法、防作弊、账号安全等;最后,作者还介绍了如何进行网络游戏的调试及问题排除。 《Unity3D网络游戏实战PDF》书籍内容深入浅出,适合初学者和中级开发者阅读。它提供了实用的方法和工具,帮助读者掌握网络游戏开发的技能,提高游戏开发的效率和质量。无论你是想开发网络游戏,还是想学习Unity3D游戏开发,本书都是不容错过的开发指南。 ### 回答2: unity3d网络游戏实战pdf是一本讲解使用Unity3D引擎开发网络游戏实战教程,内容涵盖了Unity3D的基础知识、网络编程与多人联机游戏设计。本书从基础开始,逐步讲解如何使用Unity3D引擎搭建网络游戏,包括如何进行多人联机游戏设计、实现网络通信,以及如何利用Unity3D引擎的特性实现游戏的界面设计和多人对战功能。本书不仅具有理论知识,更有大量实例和案例,可以帮助读者深刻了解Unity3D引擎的应用,提高网络游戏开发的技能和水平。这本书适合想要学习和掌握Unity3D引擎开发网络游戏的初、中级程序员、游戏开发者和爱好者阅读使用,可以帮助他们快速地了解并掌握开发网络游戏的流程和技巧。总之,如果你正在寻找一本全面且系统的Unity3D网络游戏开发教程,那么这本《unity3d网络游戏实战pdf》将是你的不二选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值