具体脚本如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
/// <summary>
/// 编码和解码
/// </summary>
public class NetEncode
{
/// <summary>
/// 将数据编码 长度+内容
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static byte[] Encode(byte[] data)
{
//整型占4个字节,所以声明一个+4的数组
byte[] result = new byte[data.Length + 4];
//使用流将编码二进制
MemoryStream ms = new MemoryStream();
BinaryWriter br = new BinaryWriter(ms);
br.Write(data.Length);
br.Write(data);
//将流中的内容复制到数组中
Buffer.BlockCopy(ms.ToArray(), 0, result, 0, (int)ms.Length);
br.Close();
ms.Close();
return result;
}
/// <summary>
/// 将数据解码
/// </summary>
/// <param name="cahce"></param>
/// <returns></returns>
public static byte[] Decode(ref List<byte> cahce)
{
//首先获取到长度,整型4字节,如果字节数不足4字节,舍弃
if (cahce.Count < 4)
{
return null;
}
//读取数据
MemoryStream ms = new MemoryStream(cahce.ToArray());
BinaryReader br = new BinaryReader(ms);
//先读取出包头的长度
int len = br.ReadInt32();
//根据长度,判断内容是否传递完毕
if (len > ms.Length - ms.Position)
{
return null;
}
//获取数据
byte[] result = br.ReadBytes(len);
//清空消息池
cahce.Clear();
//将剩余没有处理的消息重新存入消息池中
cahce.AddRange(br.ReadBytes((int)ms.Length - (int)ms.Position));
return result;
}
}
using System.Collections;
using System.Collections.Generic;
using ProtoBuf;
using UnityEngine;
//添加特性,表示可以被ProtoBuf工具序列化
[ProtoContract]
public class NetModel
{
//添加特性,表示字段可以被序列化,1可以理解为下标
[ProtoMember(1)] public int ID;
[ProtoMember(2)] public string Commit;
[ProtoMember(3)] public string Message;
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public static class NetSerilizer
{
/// <summary>
/// 将消息序列化为二进制数组
/// </summary>
/// <param name="netModel"></param>
/// <returns></returns>
public static byte[] Serialize(NetModel netModel)
{
try
{
//将二进制序列化到流中
using (MemoryStream ms = new MemoryStream())
{
//使用ProtoBuf工具序列化方法
ProtoBuf.Serializer.Serialize<NetModel>(ms, netModel);
//保存序列化后的结果
byte[] result = new byte[ms.Length];
//将流的位置设置为0,起始点
ms.Position = 0;
//将流中的内容读取到二进制数组中
ms.Read(result, 0, result.Length);
return result;
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
/// <summary>
/// 把收到的消息反序列化成对象
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public static NetModel DeSerialize(byte[] msg)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
//将消息写入流中
ms.Write(msg, 0, msg.Length);
//将流的位置归零
ms.Position = 0;
//使用工具反序列化对象
NetModel result = ProtoBuf.Serializer.Deserialize<NetModel>(ms);
return result;
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using UnityEngine;
/// <summary>
/// 模拟客户端操作
/// </summary>
public class NetUserToken
{
/// <summary>
/// 用于连接的socket
/// </summary>
private Socket socket;
/// <summary>
/// 数据缓冲区
/// </summary>
public byte[] byteBuff;
/// <summary>
/// 每次接受和发送的数据大小
/// </summary>
private readonly int size = 1024;
/// <summary>
/// 接收数据池
/// </summary>
private List<byte> receiveCache;
private bool isReceiving;
/// <summary>
/// 发送数据池
/// </summary>
private Queue<byte[]> sendCache;
private bool isSending;
/// <summary>
/// 接收到消息后的回调
/// </summary>
private Action<NetModel> receiveCallback;
public NetUserToken()
{
byteBuff = new byte[size];
receiveCache = new List<byte>();
sendCache = new Queue<byte[]>();
}
/// <summary>
/// 服务器接收客户端发送的消息
/// </summary>
/// <param name="data"></param>
public void Receive(byte[] data)
{
Debug.Log("接收数据");
//将接收到的数据放入数据池中
receiveCache.AddRange(data);
//如果没在读数据
if (!isReceiving)
{
isReceiving = true;
}
}
/// <summary>
/// 读取数据
/// </summary>
private void ReadData()
{
byte[] data = NetEncode.Decode(ref receiveCache);
//如果数据读取成功
if (null != data)
{
NetModel item = NetSerilizer.DeSerialize(data);
Debug.Log(item.ID + "," + item.Commit + "," + item.Message);
if (null != receiveCallback)
{
receiveCallback(item);
}
//尾递归,继续处理数据
ReadData();
}
else
{
isReceiving = false;
}
}
/// <summary>
/// 服务器发送消息给客户端
/// </summary>
private void Send()
{
try
{
if (sendCache.Count == 0)
{
isSending = false;
return;
}
byte[] data = sendCache.Dequeue();
int count = data.Length / size;
int len = size;
for (int i = 0; i < count + 1; i++)
{
if (i == count)
{
len = data.Length - i * size;
}
socket.Send(data, i * size, len, SocketFlags.None);
}
Debug.Log("发送成功");
Send();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public void WriteSendData(byte[] data)
{
sendCache.Enqueue(data);
if (!isSending)
{
isSending = true;
Send();
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class PBTest : MonoBehaviour
{
// Use this for initialization
void Start()
{
//创建对象
NetModel item = new NetModel() { ID = 1, Commit = "马三", Message = "Unity" };
//序列化对象
byte[] temp = Serialize(item);
Debug.Log("序列化数组长度:" + temp.Length);
//反序列化为对象
NetModel result = DeSerialize(temp);
Debug.Log(result.ID + "," + result.Commit + "," + result.Message);
}
/// <summary>
/// 将消息序列化为二进制数组
/// </summary>
/// <param name="netModel"></param>
/// <returns></returns>
private byte[] Serialize(NetModel netModel)
{
try
{
//将二进制序列化到流中
using (MemoryStream ms = new MemoryStream())
{
//使用ProtoBuf工具序列化方法
ProtoBuf.Serializer.Serialize<NetModel>(ms, netModel);
//保存序列化后的结果
byte[] result = new byte[ms.Length];
//将流的位置设置为0,起始点
ms.Position = 0;
//将流中的内容读取到二进制数组中
ms.Read(result, 0, result.Length);
return result;
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
/// <summary>
/// 把收到的消息反序列化成对象
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
private NetModel DeSerialize(byte[] msg)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
//将消息写入流中
ms.Write(msg, 0, msg.Length);
//将流的位置归零
ms.Position = 0;
//使用工具反序列化对象
NetModel result = ProtoBuf.Serializer.Deserialize<NetModel>(ms);
return result;
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}