Unity【Multiplayer 多人在线】- Socket 通用客户端网络模块(三)、Send 发送数据

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

介绍

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

一、通用服务端框架

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

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

        (三)、Protobuf 通信协议

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

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

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

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

 二、通用客户端网络模块

        (一)、Connect 连接服务端

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

        (三)、Send 发送数据

        (四)、Close 关闭连接

本篇内容:

Send 发送数据:

首先定义写入队列writeQueue,并将writeQueue在初始化函数Init中进行初始化:


  
  1. //写入队列
  2. private static Queue<ByteArray> writeQueue;

 Send回调函数中会判断写入队列是否还有数据,如果写入队列不为空,继续发送数据:


  
  1. //发送数据
  2. public static void Send(IExtensible proto)
  3. {
  4. //状态判断
  5. if (socket == null || !socket.Connected) return;
  6. if (isConnecting || isClosing) return;
  7. //数据编码
  8. byte[] nameBytes = ProtoUtility.EncodeName(proto);
  9. byte[] bodyBytes = ProtoUtility.Encode(proto);
  10. int len = nameBytes.Length + bodyBytes.Length;
  11. byte[] sendBytes = new byte[2 + len];
  12. //组装长度
  13. sendBytes[0] = (byte)(len % 256);
  14. sendBytes[1] = (byte)(len / 256);
  15. //组装名字
  16. Array.Copy(nameBytes, 0, sendBytes, 2, nameBytes.Length);
  17. //组装消息体
  18. Array.Copy(bodyBytes, 0, sendBytes, 2 + nameBytes.Length, bodyBytes.Length);
  19. //写入队列
  20. ByteArray ba = new ByteArray(sendBytes);
  21. int count = 0;
  22. lock (writeQueue)
  23. {
  24. writeQueue.Enqueue(ba);
  25. count = writeQueue.Count;
  26. }
  27. //Send
  28. if (count == 1)
  29. {
  30. socket.BeginSend(sendBytes, 0, sendBytes.Length, 0, SendCallback, socket);
  31. }
  32. }
  33. //Send回调
  34. private static void SendCallback(IAsyncResult ar)
  35. {
  36. //获取State、EndSend的处理
  37. Socket socket = (Socket)ar.AsyncState;
  38. //状态判断
  39. if (socket == null || !socket.Connected) return;
  40. //EndSend
  41. int count = socket.EndSend(ar);
  42. //获取写入队列第一条数据
  43. ByteArray ba;
  44. lock (writeQueue)
  45. {
  46. ba = writeQueue.First();
  47. }
  48. //完整发送
  49. ba.readIdx += count;
  50. if (ba.length == 0)
  51. {
  52. lock (writeQueue)
  53. {
  54. writeQueue.Dequeue();
  55. ba = writeQueue.Count > 0 ? writeQueue.First() : null;
  56. }
  57. }
  58. //继续发送
  59. if (ba != null)
  60. {
  61. socket.BeginSend(ba.bytes, ba.readIdx, ba.length, 0, SendCallback, socket);
  62. }
  63. //正在关闭
  64. else if (isClosing)
  65. {
  66. socket.Close();
  67. }
  68. }

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

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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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