【GameFramework框架内置模块】11、网络(Network)

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • QQ群:398291828

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

【GameFramework框架】系列教程目录:
https://blog.csdn.net/q764424567/article/details/135831551

二、正文

2-1、介绍

网络(Network)模块,主要是提供了使用Socket长连接的功能,支持TCP协议,同时兼容Ipv4IPv6两个版本。

用户可以同时建立多个连接与多个服务器进行通信,比如连接了常规的服务器以外,还想连接语音聊天服务器。

如果想要接入ProtoBuf之类的协议库,只要派生自Packet类并实现自己的消息包类即可使用。

2-2、使用说明

这里以StarForce示例项目为例,这个项目演示了接入ProtoBuf协议库后,连接Socket、发送数据、接收数据的过程。

2-2-1、接入ProtoBuf协议库

1、生成Proto数据类

namespace StarForce
{//使用ProtoContract标签[Serializable, ProtoContract(Name = @"CSHeartBeat")]public class CSHeartBeat : CSPacketBase{public override int Idpublic override void Clear()}
}

2、序列化

//序列化
CSHeartBeat packet = ReferencePool.Acquire<CSHeartBeat >();
Serializer.Serialize(m_CachedStream, packet);//反序列化
CSHeartBeat packet = Serializer.Deserialize<SCHeartBeat >(m_CachedStream);

3、解数据

//获取header包
SCPacketHeader scPacketHeader = packetHeader as SCPacketHeader;
//获取数据包类型
Type packetType = GetServerToClientPacketType(scPacketHeader.Id);
//解数据
Packet packet = (Packet)RuntimeTypeModel.Default.DeserializeWithLengthPrefix(source, ReferencePool.Acquire(packetType), packetType, PrefixStyle.Fixed32, 0);

接到数据后,要进行解包,包体为了防止TCP粘包问题,会对数据包的格式进行包装,比如说【事件id+数据长度+数据体】。

StarForce中,将事件id和数据长度封装到PacketHeader类中,在解包时就不用考虑字节的问题,通过Protobuf来操作即可。

2-2-2、使用网络(Network)模块

1、连接Socket

private const string ip = "127.0.0.1";
private const int port = 3563;protected override void OnInit(object userData)
{var channel = GameEntry.Network.CreateNetworkChannel("Default", ServiceType.Tcp, new NetworkChannelHelper());channel.Connect(IPAddress.Parse(ip), port);
}

2、发送数据

public void OnStartButtonClick()
{CS_LoginVerify login = ReferencePool.Acquire<CS_LoginVerify>();login.account = GetAcount();var channel = GameEntry.Network.GetNetworkChannel("Default");channel .Send(login);
}

3、接收数据

public partial class SC_LoginVerifyHandler : PacketHandlerBase
{public override void Handle(object sender, Packet packet){var data = (SC_LoginVerify)packet;//.....}
}

2-3、实现及代码分析

NetworkManager.cs

网络管理器,负责维护网络连接,每一个网络连接相当于一个网络频道,比如有多个网络连接,就建立多个网络频道,当一个网络连接断开后,直接再新建一个网络频道,就可以防止数据混乱。

namespace GameFramework.Network
{/// <summary>/// 网络管理器。/// </summary>public class NetworkManager{/// <summary>/// 网络频道。/// </summary>private readonly Dictionary<string, NetworkChannelBase> m_NetworkChannels;/// 用户自定义网络错误事件。event EventHandler<NetworkCustomErrorEventArgs> NetworkCustomError;/// 检查是否存在网络频道。bool HasNetworkChannel(string name);/// 获取网络频道。INetworkChannel GetNetworkChannel(string name);/// 获取所有网络频道。INetworkChannel[] GetAllNetworkChannels();/// 获取所有网络频道。void GetAllNetworkChannels(List<INetworkChannel> results);/// 创建网络频道。INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper);/// 销毁网络频道。bool DestroyNetworkChannel(string name);}
}

NetworkChannel.cs

网络频道接口,承接上一个脚本的网络频道的概念,这个是对网络频道,也就是一个Socket的封装,处理Socket的连接和断开,以及数据的发送和接收。

namespace GameFramework.Network
{/// <summary>/// 网络频道接口。/// </summary>public interface INetworkChannel{/// 获取网络频道名称。string Name/// 获取网络地址类型。AddressFamily AddressFamily/// 获取网络频道所使用的 Socket。Socket Socket/// 获取网络服务类型。ServiceType ServiceType/// 注册网络消息包处理函数。void RegisterHandler(IPacketHandler handler);/// 连接到远程主机。void Connect(IPAddress ipAddress, int port);/// 关闭网络频道。void Close();/// 向远程主机发送消息包。void Send<T>(T packet) where T : Packet;}
}

NetworkManager.TcpNetworkChannel.cs

TcpNetworkChannel是框架基于TCP协议实现的网络频道,TCP也是我们常用的长连接方式。

namespace GameFramework.Network
{/// <summary>/// TCP 网络频道。/// </summary>public interface TcpNetworkChannel {// 建立连接private void ConnectAsync(IPAddress ipAddress, int port, object userData){m_Socket.BeginConnect(ipAddress, port, m_ConnectCallback, new ConnectState(m_Socket, userData));}// 数据发送private void SendAsync(){//序列化消息,添加包头serializeResult = m_NetworkChannelHelper.Serialize(packet, m_SendState.Stream);//发送m_Socket.BeginSend(m_SendState.Stream.GetBuffer(), (int)m_SendState.Stream.Position, (int)(m_SendState.Stream.Length - m_SendState.Stream.Position), SocketFlags.None, m_SendCallback, m_Socket);}// 数据接收private void ReceiveAsync(){//接收网络流m_Socket.BeginReceive(m_ReceiveState.Stream.GetBuffer(), (int)m_ReceiveState.Stream.Position, (int)(m_ReceiveState.Stream.Length - m_ReceiveState.Stream.Position), SocketFlags.None, m_ReceiveCallback, m_Socket);//解析消息头IPacketHeader packetHeader = m_NetworkChannelHelper.DeserializePacketHeader(m_ReceiveState.Stream, out customErrorData);m_ReceiveState.PrepareForPacket(packetHeader);//解析消息体Packet packet = m_NetworkChannelHelper.DeserializePacket(m_ReceiveState.PacketHeader, m_ReceiveState.Stream, out customErrorData);}}
}

NetworkChannel对数据的发送和接收处理,中间都会穿插一部NetworkChannelHelper的处理。

  • 发送数据时,有一个Helper的Serialize序列化数据的处理。
  • 接收数据时,有一个DeserializePacketHeader和DeserializePacket解析数据的处理。

这就是GF框架的精妙处,它把可定制的代码逻辑,都交给了Helper来处理,这样我们在扩展框架的同时,又完全不需要修改框架的核心结构。完全符合开闭原则。

NetworkChannelHelper.cs

网络频道辅助器接口,NetworkChannelHelper可以理解为把我们所需要发送 和接收的数据进行序列化和反序列化处理的工具。

NetworkChannelHelper的基本结构如下所示:

namespace GameFramework.Network
{/// <summary>/// 网络频道辅助器接口。/// </summary>public interface INetworkChannelHelper{/// 初始化网络频道辅助器。void Initialize(INetworkChannel networkChannel);/// 关闭并清理网络频道辅助器。void Shutdown();/// 准备进行连接。void PrepareForConnecting();/// 发送心跳消息包。bool SendHeartBeat();/// 序列化消息包。bool Serialize<T>(T packet, Stream destination) where T : Packet;/// 反序列化消息包头。IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData);/// 反序列化消息包。Packet DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData);}
}

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

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

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

相关文章

10 封装dml,dql

将xxx_xxx的形式转换为小驼峰 param column 获得的sql中的列名 return 小驼峰的形式的属性名 处理dml 处理dml package com.aistart.tech.utils;import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.List;public class BaseDao …

RabbitMQ集群部署

集群部署 我们看看如何安装RabbitMQ的集群。 1.集群分类 在RabbitMQ的官方文档中&#xff0c;讲述了两种集群的配置方式&#xff1a; 普通模式&#xff1a;普通模式集群不进行数据同步&#xff0c;每个MQ都有自己的队列、数据信息&#xff08;其它元数据信息如交换机等会同…

2024年高压电工证模拟考试题库及高压电工理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年高压电工证模拟考试题库及高压电工理论考试试题是由安全生产模拟考试一点通提供&#xff0c;高压电工证模拟考试题库是根据高压电工最新版教材&#xff0c;高压电工大纲整理而成&#xff08;含2024年高压电工证…

消防游戏演练,消防科普游戏开发

当今社会&#xff0c;消防安全意识日益受到重视。在这样的背景下&#xff0c;开发一款消防演练游戏不仅能够为人们提供娱乐&#xff0c;更重要的是可以教育玩家正确应对火灾等紧急情况的方法和技能。下面将详细介绍开发消防演练游戏的步骤和关键考虑因素。 游戏概念和设计 消…

【Leetcode每日一题】 递归 - Pow(x, n)(难度⭐⭐)(40)

1. 题目解析 题目链接&#xff1a;50. Pow(x, n) 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 在这个算法中&#xff0c;递归函数的任务是求出 x 的 n 次方。那么&#xff0c;这个函数是怎么工作的呢&#xff1f;它…

es 集群核心概念以及实践

节点概念&#xff1a; 节点是一个Elasticsearch的实例 本质上就是一个JAVA进程一台机器上可以运行多个Elasticsearch进程&#xff0c;但是生产环境一般建议一台机器上只运行一个Elasticsearch实例 每一个节点都有名字&#xff0c;通过配置文件配置&#xff0c;或者启动时候 -…

Android Zygote的面试问题

问题&#xff1a; 什么是Zygote进程在Android系统中的作用&#xff1f; 答案&#xff1a; Zygote是Android系统中的一个核心进程&#xff0c;它的主要作用是作为系统启动和Android应用程序进程的母进程。Zygote预加载了Android框架层和核心库&#xff0c;通过复制自身创建新的应…

软件工程-第5章 结构化设计

5.1 总体设计的目标及其表示方法 5.2 总体设计 变换设计基本步骤&#xff1a; 第1步&#xff1a;设计准备--复审并精华系统模型&#xff1b; 第2步&#xff1a;确定输入、变换、输出这三部分之间的边界&#xff1b; 第3步&#xff1a;第一级分解--系统模块结构图顶层和第一层…

安卓面试题多线程 116-120

116. 简述多线程同步和互斥有几种实现方法,都是什么 ?线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。 线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性…

产品软文怎么写?媒介盒子分享公式

软文写出来的目的除了提高品牌知名度外&#xff0c;还需要推广产品&#xff0c;当企业新品上市、推广产品以及营销产品的时候&#xff0c;就需要产品类软文出手。然而产品软文想要写好还需要一定的技巧&#xff0c;今天媒介盒子就来和大家分享&#xff1a;产品软文写作公式。 一…

【C++】每日一题 56 合并区间

以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 #include <iostream> #include <vector> #…

【详细讲解如何快速上手Vue.js框架】

如何快速上手Vue.js框架 1. 前言2. 理解Vue.js的核心概念3. 搭建开发环境4. 创建第一个项目5. 学习基础6. 进阶概念7. 最佳实践和模式8. 构建和部署9. 持续学习10. 实际操作 &#x1f308;&#x1f308;&#x1f308;欢迎 &#x1f308;&#x1f308;&#x1f308; &#x1f38…

谷歌搜索技巧

搜技术书籍pdf&#xff1a; xxx书: filetype:pdf 搜电影&#xff1a; 周处除杀害:torrent 搜图片&#xff1a; 狗: 500X500 即可找到相关分辨率大小的&#x1f436;图 平常搜索 一般为浅搜索&#xff0c;加上引号 为 高精度搜索/深度搜索 年份搜索&#xff1a; 在问题的后面…

jsp页面显示乱码问题

页面展示乱码&#xff0c;以为是tomcat或者eclipse的问题&#xff0c;将tomcat和eclipse的默认编码格式都设置为了UTF-8,访问页面还是乱码&#xff0c;于是在代码中加入了一行代码&#xff1a; <% page language"java" contentType"text/html; charsetUTF-8…

把txt、pdf等文件转为一行一行的doccano数据集输入格式

文章目录 doccano 数据集导入简介代码实现代码运行结果代码公开 doccano 数据集导入 在Doccano 导入数据集时&#xff0c;使用TextLine的文件格式&#xff0c;导入的文件需要为一行一行文本的数据格式&#xff0c;每一行文本在导入Doccano后就是一条数据。 简介 主要工作说明…

深入了解Android垃圾回收机制

文章目录 一、内存分配二、垃圾回收触发条件三、GC算法3.1 Dalvik虚拟机的GC算法3.2 ART的GC算法 四、优化GC性能五、监控GC耗时情况六、总结 在Android应用开发中&#xff0c;内存管理和垃圾回收&#xff08;GC&#xff09;对于应用性能和稳定性至关重要。理解GC机制有助于我们…

[linux]--关于进程概念(下)

目录 孤儿进程 环境变量 将程序放到PATH路径下 设置PATH环境变量 设置别名 环境变量相关的命令 环境变量的组织方式​编辑 通过系统调用获取环境变量 环境变量通常是具有全局属性的 进程优先级 查看系统进程 用top命令更改已存在进程的nice&#xff1a; 程序地址空…

(附源码)基于SSM的校园兼职系统设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2024年Java精品实战案例《100套》 &#x1f345;文末获取源码联系&#x1f345; &#x1f31…

CCF-CSP认证考试 202303-4 星际网络II 100分题解

更多 CSP 认证考试题目题解可以前往&#xff1a;CSP-CCF 认证考试真题题解 原题链接&#xff1a; 202303-4 星际网络II 时间限制&#xff1a; 2.0s 内存限制&#xff1a; 1.0GB 问题描述 随着星际网络的进一步建设和规模的增大&#xff0c;一个新的问题出现在网络工程师面前…

uniapp ios证书失效

前面是按照网上查找的方法 作者大大的地址 1、一个ios账户&#xff08;688付费版&#xff09; 2、登录 Apple Developer 3、创建Identifiers ps&#xff1a;创建时需继承苹果的sdk&#xff0c;只需要一个就行 点击continue再点击Register即可 4、创建.cer证书 &…