Unity【Multiplayer 多人在线】- Socket 通用服务端框架(二)、客户端信息类和通用缓冲区结构

举报
CoderZ1010 发表于 2022/09/25 06:43:06 2022/09/25
【摘要】 介绍         在阅读了罗培羽著作的Unity3D网络游戏实战一书后,博主综合自己的开发经验与考虑进行部分修改和调整,将通用的客户端网络模块和通用的服务端框架进行提取,形成专栏,介绍Socket网络编程,希望对其他人有所帮助。目录如下: &nbsp...

介绍

        在阅读了罗培羽著作的Unity3D网络游戏实战一书后,博主综合自己的开发经验与考虑进行部分修改和调整,将通用的客户端网络模块和通用的服务端框架进行提取,形成专栏,介绍Socket网络编程,希望对其他人有所帮助。目录如下:

    一、通用服务端框架

        (一)、定义套接字和多路复用​​​​​​

        (二)、客户端信息类和通用缓冲区结构

        (三)、Protobuf 通信协议

        (四)、数据处理和关闭连接

        (五)、Messenger 事件发布、订阅系统

        (六)、单点发送和广播数据

        (七)、时间戳和心跳机制

 二、通用客户端网络模块

        (一)、Connect 连接服务端

        (二)、Receive 接收并处理数据

        (三)、Send 发送数据

        (四)、Close 关闭连接

本篇内容:

客户端信息类Client:

每一个客户端都会包含一个与服务器连接的Socket套接字和字节数据读写缓冲区,定义相关内容如下:


  
  1. using System.Net.Sockets;
  2. namespace SK.Framework.Sockets
  3. {
  4. /// <summary>
  5. /// 客户端信息类
  6. /// </summary>
  7. public class Client
  8. {
  9. /// <summary>
  10. /// 套接字
  11. /// </summary>
  12. public Socket socket;
  13. /// <summary>
  14. /// 缓冲区
  15. /// </summary>
  16. public ByteArray readBuff;
  17. /// <summary>
  18. /// 构造函数
  19. /// </summary>
  20. /// <param name="socket">套接字</param>
  21. public Client(Socket socket)
  22. {
  23. this.socket = socket;
  24. readBuff = new ByteArray();
  25. }
  26. }
  27. }

通用缓冲区结构ByteArray:

作为通用的缓冲区结构,ByteArray支持自动拓展,例如写入的数据长度大于缓冲区剩余长度时,缓冲区的容量会自动扩充。核心变量:readIdx读取位置、writeIdx写入位置、length缓冲区中数据长度、remain缓冲区中剩余空间。代码如下:


  
  1. namespace SK.Framework.Sockets
  2. {
  3. public class ByteArray
  4. {
  5. //默认大小
  6. private const int DEFAULT_SIZE = 1024;
  7. //初始大小
  8. private readonly int initSize = 0;
  9. //缓冲区
  10. public byte[] bytes;
  11. //读取位置
  12. public int readIdx = 0;
  13. //写入位置
  14. public int writeIdx = 0;
  15. //容量
  16. private int capacity = 0;
  17. //剩余空间
  18. public int remain { get { return capacity - writeIdx; } }
  19. //数据长度
  20. public int length { get { return writeIdx - readIdx; } }
  21. //构造函数
  22. public ByteArray(int size = DEFAULT_SIZE)
  23. {
  24. bytes = new byte[size];
  25. capacity = size;
  26. initSize = size;
  27. writeIdx = 0;
  28. readIdx = 0;
  29. }
  30. //构造函数
  31. public ByteArray(byte[] defaultBytes)
  32. {
  33. bytes = defaultBytes;
  34. capacity = defaultBytes.Length;
  35. initSize = defaultBytes.Length;
  36. readIdx = 0;
  37. writeIdx = defaultBytes.Length;
  38. }
  39. //重设尺寸
  40. public void ReSize(int size)
  41. {
  42. if (size < length) return;
  43. if (size < initSize) return;
  44. int n = 1;
  45. while (n < size)
  46. {
  47. n *= 2;
  48. }
  49. capacity = n;
  50. byte[] newBytes = new byte[capacity];
  51. Array.Copy(bytes, readIdx, newBytes, 0, writeIdx - readIdx);
  52. bytes = newBytes;
  53. writeIdx = length;
  54. readIdx = 0;
  55. }
  56. //检查并移动数据
  57. public void CheckAndMoveBytes()
  58. {
  59. if (length < 8)
  60. {
  61. MoveBytes();
  62. }
  63. }
  64. //移动数据
  65. public void MoveBytes()
  66. {
  67. if (length > 0)
  68. {
  69. Array.Copy(bytes, readIdx, bytes, 0, length);
  70. }
  71. writeIdx = length;
  72. readIdx = 0;
  73. }
  74. //写入数据
  75. public int Write(byte[] bs, int offset, int count)
  76. {
  77. if (remain < count)
  78. {
  79. ReSize(length + count);
  80. }
  81. Array.Copy(bs, offset, bytes, writeIdx, count);
  82. writeIdx += count;
  83. return count;
  84. }
  85. //读取数据
  86. public int Read(byte[] bs, int offset, int count)
  87. {
  88. count = Math.Min(count, length);
  89. Array.Copy(bytes, readIdx, bs, offset, count);
  90. readIdx += count;
  91. CheckAndMoveBytes();
  92. return count;
  93. }
  94. //读取Int16
  95. public Int16 ReadInt16()
  96. {
  97. if (length < 2) return 0;
  98. Int16 ret = (Int16)((bytes[readIdx + 1]) << 8 | bytes[readIdx]);
  99. readIdx += 2;
  100. CheckAndMoveBytes();
  101. return ret;
  102. }
  103. //读取Int32
  104. public Int32 ReadInt32()
  105. {
  106. if (length < 4) return 0;
  107. Int32 ret = (Int32)((bytes[readIdx + 3] << 24) |
  108. (bytes[readIdx + 2] << 16) |
  109. (bytes[readIdx + 1] << 8) |
  110. bytes[readIdx + 0]);
  111. readIdx += 4;
  112. CheckAndMoveBytes();
  113. return ret;
  114. }
  115. }
  116. }

参考资料:《Unity3D网络游戏实战》(第2版)罗培羽 著

文章来源: coderz.blog.csdn.net,作者:CoderZ1010,版权归原作者所有,如需转载,请联系作者。

原文链接:coderz.blog.csdn.net/article/details/124053571

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。