Unity网络通信笔记

需求

首先要意识到网络通信面对的是一个怎么样的情景:

  1. 服务器会连任意个客户端,任意时刻可能有客户端连入连出;
  2. 服务端和客户端可能任意时刻给对方发消息,所以双方都要一直准备好接收。但是两端还有别的事要做,通信不能阻塞主线程;
  3. 发的只能是字节数组,发时要把数据类序列化,接收时反序列化,序列化反序列化程序是每个数据类专门写一个还是写一个通用的?通用的怎么写?
  4. 发的只能是字节数组,但是发的数据类有多种,需要一个数据类型头标记这是哪个数据类。(如果是二进制序列化用于保存文件,就可以通过文件路径知道对应的数据类,无需这个标记ID,但网络通信是一条信道传递多种数据类);
  5. 定义通信的需求,什么情况下需要发数据?发什么数据类?对方回复什么?相当于自定义一套协议。不过没设计好也可以先写纯收发字节数组的模块;

可以把通信部分分成两个模块:序列化反序列化模块、通信模块。前者负责:

  1. 在数据类和字节数组之间转换;
  2. 发送时在数据类的字节数组前加上标记数据类类型的ID;
  3. 接收时根据头的ID判断数据类类型,然后反序列化成数据类;

通信模块只管接收字节数组,发送给另一端,和接收另一端发来的字节数组。 

通信模块

  1. 服务端会连很多客户端,为了存连接的所有客户端可以用一个字典;
  2. 服务端要知道客户端断开了连接,可以通过判断socket.Receive(buffer)返回的数是否为0.没收到消息时这个函数会阻塞线程,不返回,若返回0则说明客户端断开了连接。需要紧接着执行socket.Shutdown()和socket.Close();
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Mercenaria;
using UnityEngine;public class MyNetManager : MonoSingletonDontDestroy<MyNetManager>
{Socket socket;Queue<byte[]> queueSend = new Queue<byte[]>();Queue<byte[]> queueReceive = new Queue<byte[]>();Thread threadSend, threadReceive;byte[] buffer = new byte[1024 * 20];int lenReveive;bool on;void Start(){Connect("127.0.0.1", 8080);}void Update(){if (queueReceive.Count > 0){Debug.Log(queueReceive.Dequeue());}}public void Connect(string ip, int port){if (on){return;}if (socket == null){socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);}IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);try{socket.Connect(iPEndPoint);on = true;ThreadPool.QueueUserWorkItem(SendMessage);ThreadPool.QueueUserWorkItem(ReceiveMessage);}catch (SocketException ex){if (ex.ErrorCode == 10061){
#if UNITY_EDITORDebug.Log("服务器拒绝连接");
#endif}else{
#if UNITY_EDITORDebug.Log("连接失败" + ex.Message);
#endif}}}public void Send(byte[] message){byte[] bufferSend = new byte[message.Length];Array.Copy(message,bufferSend,message.Length);//深拷贝queueSend.Enqueue(bufferSend);}void SendMessage(object obj){while (on){if (queueSend.Count > 0){socket.Send(queueSend.Dequeue());}}}void ReceiveMessage(object obj){while (on){if (socket.Available > 0){lenReveive = socket.Receive(buffer);byte[] data=new byte[buffer.Length];Array.Copy(buffer,data,buffer.Length);queueReceive.Enqueue(data);}}}public void Close(){if (socket != null){socket.Shutdown(SocketShutdown.Both);socket.Close();on = false;threadSend = null;threadReceive = null;}}void OnDestroy(){Close();}
}

序列化反序列化模块

如果暂时没有实战项目,纯为了学习,该怎么写数据类序列化反序列化的部分?

是否要写一个能序列化任意数据类的程序?

考虑到还要加上分辨数据类的ID头,这个ID头和数据类的对应关系是人为规定的。序列化之后就是一个字节数组,已经无法知道是什么数据类了,所以加数据类ID必须在序列化的函数里。那么这个《能序列化任意数据类的程序》也就不再能序列化任意数据类了。然后意识到“能序列化任意数据类”对网络传输意义不大,任何数据类都要通过头ID才知道怎么反序列化。

不过《能序列化任意数据类的程序》还是能解决对大型数据类一个个字段序列化太麻烦的问题。

使用GetFields()的“万能”序列化程序还有一个问题,就是不能序列化基本数据类型,只能序列化class。

综上,这个《能序列化任意数据类的程序》对输入的object需要先用is判断具体类型,加ID头,然后用GetFields()、循环序列化,如果要传输的数据类种类很多、数据类字段很多,才有优势。

分包粘包处理

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86451.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EasyRTC嵌入式音视频通信SDK音视频功能驱动视频业务多场景应用

一、方案背景​ 随着互联网技术快速发展&#xff0c;视频应用成为主流内容消费方式。用户需求已从高清流畅升级为实时互动&#xff0c;EasyRTC作为高性能实时音视频框架&#xff0c;凭借低延迟、跨平台等特性&#xff0c;有效满足市场对多元化视频服务的需求。 二、EasyRTC技术…

《MLB美职棒》勇士队排名·棒球1号位

亚特兰大勇士队&#xff08;Atlanta Braves&#xff09;是美国职业棒球大联盟&#xff08;MLB&#xff09;中历史最悠久的球队之一&#xff0c;隶属于国家联盟&#xff08;NL&#xff09;东区。 球队基本信息 成立时间&#xff1a;1871年&#xff08;前身为波士顿红袜帽队&…

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…

每日一令:Linux 极简通关指南 - 汇总

专栏列表 &#x1f4bb; 每日一令&#xff1a;Linux 极简通关指南 (25篇) 【基础】每天掌握一个Linux命令 - nsenter&#xff1a;深入容器与命名空间的利器 发布于 2025-06-08 22:27:04【基础】 每天掌握一个Linux命令 - journalctl&#xff1a;系统日志管理的得力助手 发布于…

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术点解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术点解析 第一轮&#xff1a;基础概念问题 请解释Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; 程序员JY回答&#xff1a;Spring框架的核心容器是IoC容器&#xff08;控制反转…

渗透测试服务如何全方位评估企业安全状况并揭示潜在缺陷?

渗透测试服务通过模拟攻击行为&#xff0c;对企业整体安全状况进行全方位评估&#xff0c;旨在揭示潜在的安全缺陷并制定相应的修复措施。以下为渗透测试服务报告的核心内容。 测试类型适配 外部渗透测试旨在模仿外部网络攻击者&#xff0c;尝试突破企业网络安全防线&#xf…

SwiftUI 数据绑定与视图更新(@State、@ObservedObject、@EnvironmentObject)

引言 在 SwiftUI 中&#xff0c;界面并不是通过手动刷新来更新的&#xff0c;而是由状态驱动的。当状态发生变化&#xff0c;SwiftUI 会自动识别哪些视图需要重绘&#xff0c;从而保持 UI 与数据的一致性。这种声明式的方式大大简化了界面开发的流程&#xff0c;但也带来一个问…

21-Oracle 23 ai-Automatic SQL Plan Management(SPM)

小伙伴们&#xff0c;有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL&#xff0c; 性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。 于是SPM定位开始&#xff0c;OCM考试中SPM必考。 其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题…

[Linux] 命令行管理文件

目录 FHS 文件路径导航 ls命令 tree命令 stat命令 touch命令 命令行管理文件 mkdir命令 cp命令 mv命令 rm和rmdir命令 软链接 硬链接 软连接硬链接区别 shell扩展匹配文件 FHS FHS采用树形结构组织文件&#xff0c;定义了系统中每个区域的用途、所需要的最小构…

自动化过程中,如何定位一闪而过的toast?

MutationObserver实战&#xff1a;动态捕获页面Toast消息的终极解决方案 一、代码全景解析 const observer new MutationObserver((mutations) > {// 回调函数主体... });observer.observe(document.body, {childList: true,subtree: true });核心组件解析 组件作用重要…

基于 Three.js 的数字雨波纹效果技术解析

文章目录 一、基础环境搭建与 Three.js 引入​二、场景与相机设置​三、后期处理:光晕效果的实现​四、纹理创建:定制雨滴、波纹和水花外观​五、粒子系统:模拟雨滴下落与交互​1,雨滴粒子系统​2,波纹与水花系统​六、动画循环与交互响应​本文将深入剖析一段实现该效果的…

联想拯救者R9000P 网卡 Realtek 8852CE Ubuntu/Mint linux 系统睡眠后,无线网卡失效

联想拯救者R9000P 网卡型号 Realtek PCle GbE Family Controller Realtek 8852CE WiFi 6E PCI-E NIC 系统版本 Ubuntu 24.04 / mint 22.1 问题现象 rtw89_8852ce&#xff0c;Link is Down&#xff0c;xtal si not ready&#xff0c;mac init fail&#xff0c;xtal si not …

Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;Floyd 快慢指针法&#xff08;…

安宝特科技丨Pixee Medical产品获FDA认证 AR技术赋能骨科手术智能化

法国医疗科技企业Pixee Medical宣布&#xff0c;其研发的智能骨科手术导航系统 Knee NexSight 解决方案正式通过美国食品药品监督管理局&#xff08;FDA&#xff09;510(k)认证&#xff0c;标志着增强现实&#xff08;AR&#xff09;技术在医疗领域的商业化应用迈出关键一步。 …

操作系统的概念,功能和目标

小懒来了&#xff01; 操作系统学习正式开始&#xff0c;day1是小懒O&#xff01; Using blogs to organize and understand knowledge is a good way, lets learn, operating systems Chapter 1,Lets look at it &#xff08;一&#xff09;预备知识 一.什么是接口 1.假设我…

STM32使用水位传感器

1.1 介绍&#xff1a; 水位传感器专为水深检测而设计&#xff0c;可广泛用于感应降雨&#xff0c;水位&#xff0c;甚至液体泄漏。当将水位传感器放入水中时&#xff0c;水位没过铜线越多模拟值越大&#xff0c;读取水深传感器模块的模拟值&#xff0c;在串口打印出来&#xf…

Spring事务传播机制有哪些?

导语&#xff1a; Spring事务传播机制是后端面试中的必考知识点&#xff0c;特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发&#xff0c;全面剖析Spring事务传播机制&#xff0c;帮助你答得有…

相机Camera日志实例分析之一:相机Camx【前置慢动作分辨率切换720P、1080P录制】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 1、打…

OpenHarmony标准系统-HDF框架之I2C驱动开发

文章目录 引言I2C基础知识概念和特性协议&#xff0c;四种信号组合 I2C调试手段硬件软件 HDF框架下的I2C设备驱动案例描述驱动Dispatch驱动读写 总结 引言 I2C基础知识 概念和特性 集成电路总线&#xff0c;由串网12C(1C、12C、Inter-Integrated Circuit BUS)行数据线SDA和串…

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…