(之前写的客户端服务端收发消息 只能接收和发送字符串类型 现在写的案例在之前基础上进行修改 可以接收和发送结构类对象数据)
创建了四个脚本
1.BaseData、PlayerData、baseMsg、PlayerMsg。
其中PlayerData和baseMsg继承BaseData基类,
PlayerMsg继承baseMsg基类。
BaseMsg是消息基类,
BaseData是数据读写基类,
PlayerData是用户结构类,
PlayerMsg玩家消息处理类。
一、BaseData基类 用于数据的序列化和反序列化 代码如下
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public abstract class BaseData
{
//获取子类字节数组容量大小
public abstract int GetBytesNum();
/// <summary>
/// 把成员变量 序列化为 对应的字节数组
/// </summary>
/// <returns></returns>
public abstract byte[] Writing();
/// <summary>
/// 把2进制字节数组 反序列化到 成员变量当中
/// </summary>
/// <param name="bytes">反序列化使用的字节数组</param>
/// <param name="beginIndex">从多少索引开始解析</param>
/// <returns></returns>
public abstract int Reading(byte[] bytes,int beginIndex=0);
/// <summary>
/// 存储不同类型变量到指定的字节数组当中
/// </summary>
/// <param name="bytes">指定字节数组</param>
/// <param name="value">具体的类型值</param>
/// <param name="index">每次存储后用于记录当前索引位置的变量</param>
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 WriteShort(byte[] bytes, short value, ref int index)
{
BitConverter.GetBytes(value).CopyTo(bytes, index);
index += sizeof(short);
}
protected void WriteLong(byte[] bytes, long value, ref int index)
{
BitConverter.GetBytes(value).CopyTo(bytes, index);
index += sizeof(long);
}
protected void WriteByte(byte[] bytes, byte value, ref int index)
{
bytes[index] = value;
index += sizeof(byte);
}
protected void WriteBool(byte[] bytes, bool value, ref int index)
{
BitConverter.GetBytes(value).CopyTo(bytes, index);
index += sizeof(bool);
}
protected void WriteString(byte[] bytes, string value, ref int index)
{
//先存储string字节数组的长度
byte[] strBytes = Encoding.UTF8.GetBytes(value);
/*BitConverter.GetBytes(strBytes.Length).CopyTo(bytes, index);
index += sizeof(int);*/
WriteInt(bytes, strBytes.Length, ref index);
//再存储 string字节数组
strBytes.CopyTo(bytes, index);
index += strBytes.Length;
}
protected void writeData(byte[] bytes, BaseData data, ref int index)
{
data.Writing().CopyTo(bytes, index);
index += data.GetBytesNum();
}
/// <summary>
/// 读取不同类型变量到指定的字节数组当中
/// </summary>
/// <param name="bytes"></param>
/// <param name="index"></param>
protected int ReadInt(byte[] bytes,ref int index)
{
int value= BitConverter.ToInt32(bytes, index);
index += sizeof(int);
return value;
}
protected short ReadShort(byte[] bytes,ref int index)
{
short value = BitConverter.ToInt16(bytes, index);
index += sizeof(short);
return value;
}
protected long ReadLong(byte[] bytes,ref int index)
{
long value = BitConverter.ToInt64(bytes, index);
index += sizeof(long);
return value;
}
protected float ReadFloat(byte[] bytes,ref int index)
{
float value= BitConverter.ToSingle(bytes, index);
index += sizeof(float);
return value;
}
protected bool ReadBool(byte[] bytes, ref int index)
{
bool value=BitConverter.ToBoolean(bytes, index);
index += sizeof(bool);
return value;
}
protected byte ReadByte(byte[] bytes, ref int index)
{
byte value= bytes[index];
index += sizeof(byte);
return value;
}
protected string ReadString(byte[] bytes,ref int index)
{
//先读取长度
int length=BitConverter.ToInt32(bytes, index);
index += sizeof(int);
string value = Encoding.UTF8.GetString(bytes, index, length);
index += length;
return value;
}
protected T ReadData<T>(byte[] bytes,ref int index) where T:BaseData,new()
{
T value = new T();
index += value.Reading(bytes,index);
return value;
}
}
二、BaseMsg基类 继承BaseData 实现基类的抽象方法后,多加了一个虚方法,用于结构类添加自身消息ID
using System.Collections.Generic;
using UnityEngine;
public class BaseMsg : BaseData
{
public override int GetBytesNum()
{
throw new System.NotImplementedException();
}
public override int Reading(byte[] bytes, int beginIndex = 0)
{
throw new System.NotImplementedException();
}
public override byte[] Writing()
{
throw new System.NotImplementedException();
}
//增加一个 添加自身ID的虚方法 谁需要用谁去重写
public virtual int GetID()
{
return 0;
}
}
玩家数据类PlayerData,继承BaseData 实现了抽象方法,也就是序列化和反序列化数据类消息
using System.Collections.Generic;
using System.Text;
using UnityEngine;
/// <summary>
/// 玩家数据类
/// </summary>
public class PlayerData : BaseData
{
public string name;
public int atk;
public int lev;
public override int GetBytesNum()
{
return 4+4+4+Encoding.UTF8.GetBytes(name).Length; //拿到总长度
}
public override int Reading(byte[] bytes, int beginIndex = 0)
{
int index = beginIndex;
name=ReadString(bytes,ref index);
atk=ReadInt(bytes,ref index);
lev=ReadInt(bytes,ref index);
return index-beginIndex;
}
public override byte[] Writing()
{
int index=0;
byte[] bytes = new byte[GetBytesNum()];
WriteString(bytes, name,ref index);
WriteInt(bytes,atk,ref index);
WriteInt(bytes,lev,ref index);
return bytes;
}
}
四、PlayerMsg 继承BaseMsg 实现了玩家信息的处理
1、首先重写BaseMsg的序列化和反序列化、获取字节数组长度以及自定义消息ID(进行ID判断去处理消息)
1、public int playerID;
2、public PlayerData playerData;
int index=0; byte[] bytes = new byte[GetBytesNum()]; 先实例化一个字节数组
WriteInt(bytes, GetID(), ref index);
WriteInt(bytes, playerID, ref index);
writeData(bytes,playerData, ref index);
return bytes; Writing()方法体中的逻辑代码
接着就是反序列化方法Reading()中的功能
int index=beginIndex;
playerID = ReadInt(bytes, ref index);
playerData=ReadData<PlayerData>(bytes, ref index);
return index-beginIndex;
GetBytesNum(),获取字节数组长度方法
直接return返回出 4+
4+
playerData.GetBytesNum().length;
public override int GetID()
{
return 1001;
}
代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMsg : BaseMsg
{
public int playerID;
public PlayerData playerData;
public override byte[] Writing()
{
int index=0;
byte[] bytes = new byte[GetBytesNum()];
WriteInt(bytes, GetID(), ref index);
WriteInt(bytes, playerID, ref index);
writeData(bytes,playerData, ref index);
return bytes;
}
public override int Reading(byte[] bytes, int beginIndex = 0)
{
int index=beginIndex;
playerID = ReadInt(bytes, ref index);
playerData=ReadData<PlayerData>(bytes, ref index);
return index-beginIndex;
}
public override int GetBytesNum()
{
return 4
+ 4
+ playerData.GetBytesNum();
}
public override int GetID()
{
return 1001;
}
}