游戏实时网络通信实现【Socket与FlatBuffer协议】(一)

40 篇文章 3 订阅

游戏项目基本很难避免不与服务器端通信交互传输数据,除非你只做单机版的游戏。一般的网络游戏在游戏刚启动的时候,需要做资源热更检查处理。这里一般使用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("读取的内存流的大小超出了流本身的大小");
			}
		}

	}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Data菌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值