Unity网络开发记录(五):二进制传输消息类

news2024/10/1 18:48:23

消息类

前篇所写的CS模型只能传输字符串,在本篇文章中,尝试在服务端一次传输多种类型的数据,并在客户端接收到信息之后进行解析显示

为了实现对不同类型的数据传输,需要将不同类型的数据都转换成二进制的形式在网络中进行传输。所以要实现一个消息基类,提供各种类型数据的序列化与反序列化方法,再让需要发送的数据类继承该基类,实现其中信息的序列化等操作

using System;
using System.Text;

public abstract class BaseData 
{
    /// <summary>
    /// 获取字节数
    /// </summary>
    /// <returns></returns>
    public abstract int GetByteNum();

    /// <summary>
    /// 写入
    /// </summary>
    /// <returns></returns>
    public abstract byte[] Writing();

    /// <summary>
    /// 读取
    /// </summary>
    /// <param name="bytes"></param>
    /// <param name="index"></param>
    /// <returns></returns>
    public abstract int Reading(byte[] bytes, int index = 0);

    protected void WriteInt(byte[] bytes, int value, ref int index)
    {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(int);
    }

    protected void WriteFloat(byte[] bytes, float value, ref int index)
    {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(float);
    }

    protected void WriteString(byte[] bytes, string value, ref int index)
    {
        byte[] b1 = Encoding.UTF8.GetBytes(value);
        BitConverter.GetBytes(b1.Length).CopyTo(bytes, index);
        index += sizeof(int);
        b1.CopyTo(bytes, index);
        index += b1.Length;
    }

    protected void WriteBool(byte[] bytes, bool value, ref int index)
    {
        BitConverter.GetBytes(value).CopyTo(bytes, index);
        index += sizeof(bool);
    }

    protected void WriteData(byte[] bytes, BaseData data, ref int index)
    {
        data.Writing().CopyTo(bytes, index);
        index += data.GetByteNum();
    }

    protected int ReadInt(byte[] bytes, ref int index)
    {
        int v = BitConverter.ToInt32(bytes, index);
        index += sizeof(int);
        return v;
    }
    protected string ReadString(byte[] bytes, ref int index)
    {
        int num = BitConverter.ToInt32(bytes, index);
        index += sizeof(int);
        string v = Encoding.UTF8.GetString(bytes, index, num);
        index += num;
        return v;
    }

    protected float ReadFloat(byte[] bytes, ref int index)
    {
        float v = BitConverter.ToSingle(bytes, index);
        index += sizeof(float);
        return v;
    }

    protected bool ReadBool(byte[] bytes, ref int index)
    {
        bool v = BitConverter.ToBoolean(bytes, index);
        index += sizeof(bool);
        return v;
    }

    protected T ReadData<T>(byte[] bytes, ref int index) where T : BaseData, new()
    {
        T data = new T();
        index += data.Reading(bytes, index);
        return data;
    }
}

创建一个数据类,继承自消息基类,实现一下写入和读取的方法



using System;
using System.Text;

public class PlayerData : BaseData
{
    public int atk;
    public bool sex;
    public string name;

    public override int GetByteNum()
    {
        //int bool int(string转换成字节数组后的字节数) 字符串转字符数组后的长度 总共所占的字节数
        return sizeof(int) + sizeof(bool) + sizeof(int) + Encoding.UTF8.GetBytes(name).Length;
    }

    public override int Reading(byte[] bytes, int beginIndex = 0)
    {
        int index = beginIndex;
        atk = ReadInt(bytes, ref index);
        sex = ReadBool(bytes, ref index);
        name = ReadString(bytes, ref index);
        return index - beginIndex;
    }

    public override byte[] Writing()
    {
        int index = 0;
        byte[] bytes = new byte[GetByteNum()];
        WriteInt(bytes, atk, ref index);
        WriteBool(bytes, sex, ref index);
        WriteString(bytes, name, ref index);
        return bytes;
    }
}

为了区别不同的消息类型,需要添加一个消息头,其中有标识类型的ID

public class BaseMsg : BaseData
{
    public override int GetByteNum()
    {
        throw new System.NotImplementedException();
    }

    public override int Reading(byte[] bytes, int index = 0)
    {
        throw new System.NotImplementedException();
    }

    public override byte[] Writing()
    {
        throw new System.NotImplementedException();
    }

    public virtual int GetID()
    {
        return 0;//默认id为0
    }
}

 

创建一个最终的玩家信息类,实现读取写入方法,并设置一个标识id



public class PlayerMsg : BaseMsg
{
    public int playerID;
    public PlayerData data;

    public override int GetByteNum()
    {
        //消息头长度,int,PlayerData
        return sizeof(int) + sizeof(int) + data.GetByteNum();
    }

    public override int Reading(byte[] bytes, int index = 0)
    {
        int _index = index;
        playerID = ReadInt(bytes, ref _index);
        data = ReadData<PlayerData>(bytes, ref _index);
        return _index - index;
    }

    public override byte[] Writing()
    {
        int index = 0;
        byte[] bytes = new byte[GetByteNum()];
        WriteInt(bytes, GetID(), ref index);
        WriteInt(bytes, playerID, ref index);
        WriteData(bytes, data, ref index);
        return bytes;
    }

    public override int GetID()
    {
        return 10086;
    }

}

使用例

在服务端调用Writing方法进行序列化,然后Send。在客户端Receive后调用Reading进行反序列化

        public void Send(string info)
        {
            if (socket != null)
            {
                try
                {
                    //socket.Send(Encoding.UTF8.GetBytes(info));

                    PlayerMsg msg = new PlayerMsg();
                    msg.playerID = 114;
                    msg.data = new PlayerData();
                    msg.data.name = "123";
                    msg.data.atk = 122;
                    msg.data.sex = true;

                    socket.Send(msg.Writing());

                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);   
                }
            }
        }

先解析消息头,获得消息类型,然后根据类型进行对应解析 

    private void ReceiveMsg(object obj)
    {
        if (socket is null) return;

        while(isConnteced)
        {
            if (socket.Available > 0)
            {
                num = socket.Receive(reveiveBuffer);
                int id = BitConverter.ToInt32(reveiveBuffer, 0);
                switch (id)
                {
                    case 10086:
                        PlayerMsg msg = new PlayerMsg();
                        msg.Reading(reveiveBuffer, 4);
                        print(msg.playerID);
                        print(msg.data.atk);
                        print(msg.data.name);
                        print(msg.data.sex);
                        break;
                    default:
                        break;
                }


                //receiveQue.Enqueue(Encoding.UTF8.GetString(reveiveBuffer, 0, num));
            }
        }
    }

先启动服务端,然后在unity中运行客户端,可以看到信息解析成功了

实现了最基本的序列化反序列化通信信息的操作

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

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

相关文章

爬虫——爬虫理论+request模块

一、爬虫理论 爬虫——请求网站并提取数据的自动化程序 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟客户端发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动的抓取互联网信息的程序。 原则上&…

通信工程学习:什么是HTTP超文本传输协议

HTTP&#xff1a;超文本传输协议 HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;&#xff0c;即超文本传输协议&#xff0c;是互联网上应用最为广泛的一种网络协议&#xff0c;它位于TCP/IP四层模型当中的应用层。以下是关于HTTP协议的详细解释&#xff1a; 一、H…

太速科技-495-定制化仪器户外便携式手提触摸一体机

定制化仪器户外便携式手提触摸一体机 一、产品简介 数据处理便携式机箱平台以mini-ITX主板为基础&#xff0c;集成intel CPU处理器、FPGA、ADDA、光纤等接口&#xff0c;集成触摸显示屏&#xff0c;抗震机箱。设备小型化、一体化&#xff0c;适合实验室、办公桌面、野外…

Cannon-es.js之removeConstraint破坏约束案例

本文目录 前言最终效果1、postStep2、前置准备2.1 代码2.2 效果 3、removeConstraint3.1 解除约束代码效果 4、完整代码 前言 在3D物理引擎的广阔天地中&#xff0c;cannon-es以其轻量级、高性能和易于集成的特点&#xff0c;成为了WebGL环境中物理模拟的首选工具。它不仅能够精…

基于R语言机器学习遥感数据处理与模型空间预测

随机森林作为一种集成学习方法&#xff0c;在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性&#xff0c;随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中&#xff0c;使用Bootstrap抽样生成不同的训练集&#xff…

在海量文档中找资料?5 步打造属于自己的搜索引擎

在海量的文件中寻找那个关键的会议记录&#xff0c;是否让你感到头疼&#xff1f; 想要快速回顾上个月的项目报告&#xff0c;却迷失了一小时都找不到&#xff1f; 找报价、找库存、找供应商&#xff0c;整天忙于各种找找找&#xff1f; 现在就来教大家如何做属于自己的搜索引…

分治法c++

分治法c 快速幂题目算法代码 大整数乘法题目思路代码 快速幂 题目 三个整数 a、b 和 m&#xff0c;计算 a 的 b 次幂对 m 取模的结果ab ac abc(ab)|m(a|mb|m)|m。|为数学中的求模运算符&#xff0c;相当于c语言中的%。(ab)|m(a|mb|m)|m 算法 二分法求幂。先求ab的一半&…

【算法竞赛】尺取法

尺取法(又称为双指针、Two Pointers)是算法竞赛中一个常)用的优化技巧,用来解决序列的区间问题,操作简单,容易编程。如果区间是单调的,也常常用二分法求解,所以很多问题用尺取法和二分法都行。另外,尺取法的操作过程和分治算法的步骤很相似,有时也用在分治中。 概念 什么是尺…

位运算(4)_丢失的数字

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 位运算(4)_丢失的数字 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 温馨提示:…

学习VTK的目的和方法

1 VTK&#xff08;Visualization Toolkit&#xff09;是一个开源的跨平台软件系统&#xff0c;用于三维计算机图形学、图像处理和可视化。学习VTK的主要目的有&#xff1a; 3D可视化&#xff1a; VTK提供了丰富的工具和算法&#xff0c;可以用来可视化各种科学数据&#xff0c…

VBA数据库解决方案第十五讲:Recordset集合中单个数据的精确处理

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

windows下安装nginx和基本配置

1. 下载 Nginx 从 Nginx 官方网站下载 Windows 版本的 Nginx。访问 Nginx 官网 并选择适合 Windows 的版本。通常应选择稳定版&#xff08;Stable version&#xff09; 2. 安装 Nginx 安装 Nginx 实际上是解压下载的文件。可以选择一个适合的位置来存放 Nginx 的文件夹 例如…

【数据结构初阶】排序算法(下)冒泡排序与归并排序

文章目录 4. 交换排序4. 1 冒泡排序 5. 归并排序6. 非比较排序6. 1 计数排序 5. 排序性能分析6. 排序算法复杂度及稳定度分析 4. 交换排序 交换排序基本思想: 所谓交换**&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置**。 交换排序的特点是…

下一代性能怪兽RTX 5090最新规格更新与Blackwell架构解析

据悉&#xff0c;目前各家AIC厂商已经陆续收到NVIDIA的相关资料&#xff0c;RTX 5090、RTX 5080已经正式进入开案阶段&#xff0c;也就是厂商们开始设计各自的产品方案了。不出意外&#xff0c;年初的CES 2025上会看到RTX 5090/5080的发布。 作为NVIDIA的新一代GPU&#xff0c…

2024年健康经济与大数据研讨会(HEBD 2024)2024 Seminar on Health Economics and Big Data

在线投稿&#xff1a;学术会议-学术交流征稿-学术会议在线-艾思科蓝 2024年经济决策与人工智能国际学术会议 &#xff08;EDAI 2024&#xff09;将在2024年11月08-10日在广东省广州市隆重举行。大会邀请来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师…

理解互联网链路:从本地ISP到Tier 1 ISP运营商

1. 互联网服务提供商&#xff08;ISP&#xff09; 互联网服务提供商&#xff08;ISP&#xff09;是指提供互联网接入服务的公司或组织。它们负责将用户连接到互联网&#xff0c;并提供相关的服务&#xff0c;如电子邮件、网站托管和其他在线服务。ISP可以分为不同的层级&#…

告别转换顾虑,来试试这四款pdf转换器~

各位小伙伴们&#xff0c;大家好&#xff01;今天我来给大家分享几款超级好用的PDF转换工具&#xff0c;无论是工作还是学习&#xff0c;相信这些工具都会给你带来极大的便利&#xff1b;别看PDF文件看似难搞&#xff0c;其实有了这些神器&#xff0c;一切都变得轻松又愉快&…

在线css像素Px到百分比(%)换算器

具体请前往&#xff1a;在线Px转百分比(%)工具--将绝对像素(px)长度单位转换为相对父级元素内尺寸的相对长度单位百分比(%)

PCL GridMinimum获取栅格最低点

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 GridMinimum 栅格最低点提取 2.1.2 可视化函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长…

新农人的求索:既要种菜,也要种钱

澎湃新闻记者 何惠子 灯下立着一个玻璃瓶&#xff0c;内里空无一物&#xff0c;清晰透亮。 一只手握住瓶身。“就像这个瓶子。前途一片光明&#xff0c;但其实都在瓶子里。” 解晓巍说的是音乐——他曾梦想以此维生。事实上&#xff0c;这也适合描述农业。 在没有任何收入的202…