游戏项目基本很难避免不与服务器端通信交互传输数据,除非你只做单机版的游戏。一般的网络游戏在游戏刚启动的时候,需要做资源热更检查处理。这里一般使用http协议,如UnityWebRequest/WWW以及HttpWebRequest等已经封装好的接口来实现。而针对在网络游戏实时同步的战斗部分,则必须实现长链接,保证数据实时传输发送与接收。一般使用TCP传输协议或者“改善”的UDP协议来实现。这边使用TCP协议。详细的网络通信原理,该系列文章不做介绍,站在项目实用的角度,讲解如何一步一步地实现。
本篇文章主要介绍字节与基本类型数据转换的工具类ByteTool如何实现。主要对BitConverter 和 MemoryStream 封装。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Text;
/*
* Author:W
* 字节读写工具
* 1.基本数据类型与字节数组的相互转换
* 2.以及从内存流中读写这些基本数据类型
*/
namespace W.NetWork
{
public class ByteTool
{
/// <summary>
/// 将字节数组写入到内存流
/// </summary>
/// <param name="memoryStream">内存流</param>
/// <param name="value">目标字节数组</param>
/// <param name="isLittleEndian">是否是小端编码</param>
public static void WriteBytes(MemoryStream memoryStream,byte[] value, bool isLittleEndian = false)
{
//如果不是小端编码,则字节数组需要翻转
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(value);
memoryStream.Write(value,0,value.Length);
}
/// <summary>
/// 将short数据转换为Byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteShort(MemoryStream memoryStream,short value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes,0,2);
}
/// <summary>
/// 将ushort数据转换为byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteUShort(MemoryStream memoryStream, ushort value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 2);
}
/// <summary>
/// 将Int型数据转换为Byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteInt(MemoryStream memoryStream, int value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 4);
}
/// <summary>
/// 将uint型数据转化为byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteUInt(MemoryStream memoryStream, uint value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 4);
}
/// <summary>
/// 将Long型数据转换为Byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteLong(MemoryStream memoryStream, long value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 8);
}
/// <summary>
/// 将ulong型数据转换为Byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteULong(MemoryStream memoryStream, ulong value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 8);
}
/// <summary>
/// 将Float型数据转换Byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteFloat(MemoryStream memoryStream, float value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 4);
}
/// <summary>
/// 将Double型数据转换为Byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="isLittleEndian"></param>
public static void WriteDouble(MemoryStream memoryStream, double value, bool isLittleEndian = false)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
memoryStream.Write(bytes, 0, 8);
}
/// <summary>
/// 将string字符串数据转换为byte数组,并写入内存流
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="value"></param>
/// <param name="encodingName"></param>
/// <param name="isLittleEndian"></param>
public static void WriteString(MemoryStream memoryStream, string value,string encodingName="utf-8", bool isLittleEndian = false)
{
Encoding encoding = Encoding.GetEncoding(encodingName);
byte[] strBytes = encoding.GetBytes(value);
WriteUShort(memoryStream,(ushort)strBytes.Length,isLittleEndian);
memoryStream.Write(strBytes,0,strBytes.Length);
}
/// <summary>
/// 从内存流中读取short型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static short ReadShort(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream,2);
byte[] bytes = new byte[2];
memoryStream.Read(bytes,0,2);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToInt16(bytes,0);
}
/// <summary>
/// 从内存流中读取ushort型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static ushort ReadUShort(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 2);
byte[] bytes = new byte[2];
memoryStream.Read(bytes, 0, 2);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToUInt16(bytes, 0);
}
/// <summary>
/// 从内存流中读取int型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static int ReadInt(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 4);
byte[] bytes = new byte[4];
memoryStream.Read(bytes, 0, 4);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToInt32(bytes, 0);
}
/// <summary>
/// 从内存流中读取uint型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static uint ReadUInt(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 4);
byte[] bytes = new byte[4];
memoryStream.Read(bytes, 0, 4);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
/// <summary>
/// 从内存流中读取Long型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static long ReadLong(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 8);
byte[] bytes = new byte[8];
memoryStream.Read(bytes, 0, 8);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToInt64(bytes, 0);
}
/// <summary>
/// 从内存流中读取ulong型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static ulong ReadULong(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 8);
byte[] bytes = new byte[8];
memoryStream.Read(bytes, 0, 8);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToUInt64(bytes, 0);
}
/// <summary>
/// 从内存中读取Float型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static float ReadFloat(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 4);
byte[] bytes = new byte[4];
memoryStream.Read(bytes, 0, 4);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToSingle(bytes, 0);
}
/// <summary>
/// 从内存流中读取double型数据
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static double ReadDouble(MemoryStream memoryStream, bool isLittleEndian = false)
{
CheckReadError(memoryStream, 8);
byte[] bytes = new byte[8];
memoryStream.Read(bytes, 0, 8);
if (BitConverter.IsLittleEndian != isLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToDouble(bytes, 0);
}
/// <summary>
/// 从内存流中读取特定编码的字符串
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="encodingName"></param>
/// <param name="isLittleEndian"></param>
/// <returns></returns>
public static string ReadString(MemoryStream memoryStream, string encodingName = "utf-8", bool isLittleEndian = false)
{
ushort length = ReadUShort(memoryStream,isLittleEndian);
return ReadString(memoryStream,length,encodingName);
}
/// <summary>
/// 从内存流中读取特定长度特定编码的字符串
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="length"></param>
/// <param name="encodingName"></param>
/// <returns></returns>
public static string ReadString(MemoryStream memoryStream, ushort length, string encodingName = "utf-8")
{
CheckReadError(memoryStream, length);
Encoding encoding = Encoding.GetEncoding(encodingName);
byte[] strBytes = new byte[length];
memoryStream.Read(strBytes, 0, length);
string str = encoding.GetString(strBytes);
return str;
}
/// <summary>
/// 读取数据检查
/// </summary>
/// <param name="memoryStream"></param>
/// <param name="readSize"></param>
public static void CheckReadError(MemoryStream memoryStream,int readSize)
{
if (memoryStream.Position + readSize > memoryStream.Length)
{
Debug.LogError("读取的内存流的大小超出了流本身的大小");
}
}
}
}