Unity3d实战之Unity3d网络游戏实战篇(9):协议

学习书籍《Unity3d网络游戏实战》 罗培羽著 机械工业出版社
本文是作者在学习过程中遇到的认为值得记录的点,因此引用的代码等资源基本出资罗培羽老师的书籍,如有侵权请联系,必删。

 一套通用的服务端框架要支持不同游戏所使用的各种协议格式。所谓协议就是通信规则,例如:如果发送端直接发送一串数值数据给接收端,接收端并不知道这一串数据到底是用来做什么的,里面的数据代表了什么信息。而协议就是解决这一问题的一套规则,一套发送端和接收端都知道的规则。在要发送的数据前添加某些标志,发送端和接收端共同规定带有这个标志的数据的用途。这样,两端就可以对接收到的数据进行解析,并根据两者共同定立的规则来分辨所接收到的数据的用途。
 
 所有的协议都有相同的方法:解码、编码、获取协议名等等,以此为基础,我们可以编写一个协议的基类:
 

using System;namespace Server
{public class ProtocolBase{/// <summary>/// Decode the readBuff from start to start+length. Package readBuff as a protocol and return it./// </summary>/// <param name="readBuff">Read buff.</param>/// <param name="start">Type: int, decode begin from start.</param>/// <param name="length">Type: int, decode from begin to start+length.</param>public virtual ProtocolBase Decode(byte[] readBuff, int start, int length){return new ProtocolBase ();}/// <summary>/// Encode the protocol's content to binary array./// </summary>public virtual byte[] Encode(){return new byte[] { };}/// <summary>/// Return the protocol's name./// </summary>/// <returns>The name.</returns>public virtual string GetName(){return "";}/// <summary>/// Return the protocol's description./// </summary>/// <returns>The desc.</returns>public virtual string GetDesc(){return "";}}
}

 根据需要可以定义不同类型的协议,不同类型的协议的编码解码方式不同,如字符串协议会议字符串形式解析接收到的协议,字节流协议会以字节方式解析协议。下面给出字节流代码:

using System;
using System.Linq;namespace Server
{/// <summary>/// Bytes Protocol/// Protocol Format:///     [protocollength][protocol name][data1][data2]...///     protocollength: Int32 -> byte///     protocol name:  byte///     data:   byte/// </summary>public class ProtocolBytes : ProtocolBase{public byte[] bytes;public override ProtocolBase Decode (byte[] readBuff, int start, int length){ProtocolBytes proto = new ProtocolBytes ();proto.bytes = new byte[length];Array.Copy (readBuff, start, proto.bytes, 0, length);return (ProtocolBase)proto;}public override byte[] Encode (){return bytes;}public override string GetName (){return GetString (0);}public override string GetDesc (){if (bytes == null)return "";string str = "";for (int i = 0; i < bytes.Length; i++) {int t = (int)bytes [i];str += t.ToString () + " ";}return str;}#region Help Function#region String Operation/// <summary>/// convert the str into bytes and connect it behind the protocol./// </summary>/// <param name="str">the connected string</param>public void AddString(string str){Int32 length = str.Length;byte[] lenBytes = BitConverter.GetBytes (length);byte[] strBytes = System.Text.Encoding.UTF8.GetBytes (str);if (bytes == null)bytes = lenBytes.Concat (strBytes).ToArray ();elsebytes = bytes.Concat (lenBytes).Concat (strBytes).ToArray ();}/// <summary>/// Get a complete string from start to end./// </summary>/// <returns>string</returns>/// <param name="start">start index</param>/// <param name="end">end index</param>public string GetString(int start, ref int end){if (bytes == null)return "";if (bytes.Length < start + sizeof(Int32))return "";Int32 strLen = BitConverter.ToInt16 (bytes, start);if (bytes.Length < start + sizeof(Int32) + strLen)return "";string str = System.Text.Encoding.UTF8.GetString (bytes, start + sizeof(Int32), strLen);end = start + sizeof(Int32) + strLen;return str;}/// <summary>/// Get a complete string begin at start./// </summary>/// <returns>string</returns>/// <param name="start">start index</param>public string GetString(int start){int end = 0;return GetString (start, ref end);}#endregion#region Int32 Operation/// <summary>/// convert the Int32 into bytes and connect it behind the protocol./// </summary>/// <param name="num">Number.</param>public void AddInt32(Int32 num){byte[] numBytes = BitConverter.GetBytes (num);if (bytes == null)bytes = numBytes;elsebytes = bytes.Concat (numBytes).ToArray ();}/// <summary>/// Get a complete Int32 num from protocol's start to end./// </summary>/// <returns>Int32</returns>/// <param name="start">start index</param>/// <param name="end">end index</param>public Int32 GetInt32(int start, ref int end){if (bytes == null)return 0;if (bytes.Length < start + sizeof(Int32))return 0;end = start + sizeof(Int32);return BitConverter.ToInt32 (bytes, start);}/// <summary>/// Get a complete Int32 num from protocol's start./// </summary>/// <returns>Int32.</returns>/// <param name="start">start index</param>public Int32 GetInt(int start){int end = 0;return GetInt (start, ref end);}#endregion#region Float Operation/// <summary>/// convert the float into bytes and connect it behind the protocol./// </summary>/// <param name="num">float number</param>public void AddFloat(float num){byte[] numBytes = BitConverter.GetBytes (num);if (bytes == null)bytes = numBytes;elsebytes = bytes.Concat (numBytes).ToArray ();}/// <summary>/// Get a complete float num from protocol's start to end./// </summary>/// <returns>The float.</returns>/// <param name="start">start index</param>/// <param name="end">end index</param>public float GetFloat(int start, ref int end){if (bytes == null)return 0;if (bytes.Length < start + sizeof(float))return 0;end = start + sizeof(float);return BitConverter.ToSingle (bytes, start);}/// <summary>/// Get a complete float num from protocol's start./// </summary>/// <returns>The float.</returns>/// <param name="start">start index</param>public float GetFloat(int start){int end = 0;return GetFloat (start, ref end);}#endregion#endregion}
}

 使用Help Function中的方法可以对协议进行一定的操作,如添加协议名、添加数据等。
 我一开始在这里陷入了混乱,为什么添加String时需要打包string长度,而添加int和float时就不需要在数据前添加数据长度,后来发现这是因为string的长度是不确定的,而int和float的长度都是确定的,如Int32的长度为4byte,在获取Int时,BitConverter可以直接获取start位置往后4byte的数据并将它转化为Int32类型,显然string就不行,因此它需要添加数据长度信息。

 在完成协议后,我们就可以使用协议进行通信了,在发送协议时记得要给在发送的数据包前加上整条协议的长度信息。

【实战】Unity3d实战之Unity3d网络游戏实战篇(9):协议相关推荐

  1. 【实战】Unity3d实战之Unity3d网络游戏实战篇(11):消息分发

    Unity3d实战之Unity3d网络游戏实战篇(11):消息分发 学习书籍<Unity3d网络游戏实战> 罗培羽著 机械工业出版社 本文是作者在学习过程中遇到的认为值得记录的点,因此引用 ...

  2. 《Unity3D网络游戏实战》第7章

    <Unity3D网络游戏实战>第7章 服务端架构 总体架构 模块划分 游戏流程 Json编码解码 添加协议文件 引用System.web.Extensions 修改MsgBase类 测试 ...

  3. 视频教程-MMOARPG地下守护神_单机版实战视频课程(上部) -Unity3D

    MMOARPG地下守护神_单机版实战视频课程(上部) 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过程 ...

  4. 视频教程-MMOARPG地下守护神_单机版实战视频课程(下部) -Unity3D

    MMOARPG地下守护神_单机版实战视频课程(下部) 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过程 ...

  5. 【Unity3D实战】方块跑酷初级开发实战(一)

    [Unity3D实战]方块跑酷初级开发实战(一) 欢迎大家来到LDS的博客,今天开始我们讲解一下跑酷类游戏的基本操作,本文为原创,视频请观看[ http://www.mkcode.net/html/u ...

  6. Unity 3D网络游戏实战 pdf

    Unity 3D网络游戏实战(全) 目录: 掌握Unity3D基本元素 1.1 简单的游戏 1.1.1在场景中创建一个立方体 1.1.2编写可以使立方体运动的程序 1.1.3测试游戏1.1.4总结1. ...

  7. .NET Core实战项目之CMS 第十章 设计篇-系统开发框架设计

    这两天比较忙,周末也在加班,所以更新的就慢了一点,不过没关系,今天我们就进行千呼万唤的系统开发框架的设计.不知道上篇关于架构设计的文章大家有没有阅读,如果阅读后相信一定对架构设计有了更近一部的理解,如 ...

  8. .NET Core实战项目之CMS 第九章 设计篇-白话架构设计

    前面两篇文章给大家介绍了我们实战的CMS系统的数据库设计,源码也已经上传到服务器上了.今天我们就好聊聊架构设计,在开始之前先给大家分享一下这几天我一直在听的<从零开始学架构>里面关于架构设 ...

  9. .NET Core实战项目之CMS 第八章 设计篇-内容管理极简设计全过程

    写在前面 上一篇文章.NET Core实战项目之CMS 第七章 设计篇-用户权限极简设计全过程中我带着大家进行了权限部分的极简设计,也仅仅是一个基本的权限设计.不过你完全可以基于这套权限系统设计你的更 ...

最新文章

  1. 记录Mask RCNN调整预测网格 font大小
  2. linux 输出重定向_linux学习笔记(实验楼) 实验12 数据流重定向
  3. MariaDB 修改存储路径后启动失败问题解决
  4. 加密连接工具Cryptcat
  5. 【项目管理】敏捷原则
  6. ffmpeg 时间戳
  7. javascript Function()
  8. 浅谈iOS中的蓝牙技术(一) GameKit framework
  9. dataGridView1.DataSource多增加列,数据不进自己规定的列?
  10. qt web混合编程_VS2017+QT 混合编程-在VS控制台程序配置QT
  11. 精通Android【Android移动开发制胜宝典】
  12. 为什么使用梯度下降法或者梯度上升法
  13. java课程 数独 文库_数独教案-完整版
  14. GD32 MCU USB开发学习记录
  15. 分享五个免费图片/视频资源网站
  16. 时光飞逝,博客两周年啦
  17. php 开源项目汇总
  18. 后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例
  19. PPT文件解除编辑限制密码
  20. multithreading coding

热门文章

  1. 计算机图形在虚拟现实中的应用,虚拟现实环境中计算机图形场景实现方法研究...
  2. Javaweb图书管理系统t
  3. C#之CAD二次开发(10) 用户交互之选择集
  4. 有人说Java是世界上最好的语言,也有人说Java这几年就会没落,你怎么看呢
  5. 在自己的服务器上搭建git仓库服务器(本地推送到远程仓库、远程仓库推送到本地)
  6. 一棵高度为h的满m叉树,根节点所在的层次为第1层。若按层次自顶向下,同一层自左向右,顺序从1开始对全部结点进行编号,则结点i的第1个子结点编号j为
  7. 小白学 Python 数据分析(1):数据分析基础
  8. Welcome to the skynet wiki!
  9. 代码随想录Day02 | LeetCode977.有序数组的平方、LeetCode209.长度最小的子数组、LeetCode59.螺旋矩阵II
  10. linux光盘有iscsi安装包,linux上安装iscsi软件