基于ProtoBuf协议实现网络传输(三)
2017-04-28 15:28
435 查看
Unity版本: 5.3
使用语言: C#
写在前面
ProtoBuf是Google公司推出的一种二进制序列化工具,适用于数据的网络传输。基于Socket实现时时通信,关于数据粘包的编码和解码处理是必不可少的。
实现功能:
1.基于ProtoBuf序列化对象 2.使用Socket实现时时通信 3.数据包的编码和解码
3.数据包的编码和解码
首先,举个例子,这个月信用卡被媳妇刷爆了,面对房贷车贷的压力,我只能选择分期付款。。。那么OK了,现在我想问一下,当服务器向客户端发送的数据过大时怎么办呢?
当服务器需要向客户端发送一条很长的数据,也会“分期付款!”,服务器会把一条很长的数据分成若干条小数据,多次发送给客户端。
可是,这样就又有另外一个问题,客户端接受到多条数据之后如何解析?
这里其实就是客户端的解码。server发数据一般采用“长度+内容”的格式,Client接收到数据之后,先提取出长度来,然后根据长度判断内容是否发送完毕。
再次重申,用户在发送序列化好的消息的前,需要先编码后再发送消息;用户在接受消息后,需要解码之后再解析数据(反序列化)。
using UnityEngine; using System.Collections.Generic; using System.IO; /// <summary> /// 编码和解码 /// </summary> public class NetEncode { /// <summary> /// 将数据编码 长度+内容 /// </summary> /// <param name="data">内容</param> public static byte[] Encode(byte[] data) { //整形占四个字节,所以声明一个+4的数组 byte[] result = new byte[data.Length + 4]; //使用流将编码写二进制 MemoryStream ms = new MemoryStream(); BinaryWriter br = new BinaryWriter(ms); br.Write(data.Length); br.Write(data); //将流中的内容复制到数组中 System.Buffer.BlockCopy(ms.ToArray(), 0, result, 0, (int)ms.Length); br.Close(); ms.Close(); return result; } /// <summary> /// 将数据解码 /// </summary> /// <param name="cache">消息队列</param> public static byte[] Decode(ref List<byte> cache) { //首先要获取长度,整形4个字节,如果字节数不足4个字节 if(cache.Count < 4) { return null; } //读取数据 MemoryStream ms = new MemoryStream(cache.ToArray()); BinaryReader br = new BinaryReader(ms); int len = br.ReadInt32(); //根据长度,判断内容是否传递完毕 if(len > ms.Length - ms.Position) { return null; } //获取数据 byte[] result = br.ReadBytes(len); //清空消息池 cache.Clear(); //讲剩余没处理的消息存入消息池 cache.AddRange(br.ReadBytes((int)ms.Length - (int)ms.Position)); return result; } }
用户接受数据代码如下:
using System; using System.Collections.Generic; using System.Net.Sockets; /// <summary> /// 表示一个客户端 /// </summary> public class NetUserToken { //连接客户端的Socket public Socket socket; //用于存放接收数据 public byte[] buffer; //每次接受和发送数据的大小 private const int size = 1024; //接收数据池 private List<byte> receiveCache; private bool isReceiving; //发送数据池 private Queue<byte[]> sendCache; private bool isSending; //接收到消息之后的回调 public Action<NetModel> receiveCallBack; public NetUserToken() { buffer = new byte[size]; receiveCache = new List<byte>(); sendCache = new Queue<byte[]>(); } /// <summary> /// 服务器接受客户端发送的消息 /// </summary> /// <param name="data">Data.</param> public void Receive(byte[] data) { UnityEngine.Debug.Log("接收到数据"); //将接收到的数据放入数据池中 receiveCache.AddRange(data); //如果没在读数据 if(!isReceiving) { isReceiving = true; ReadData(); } } /// <summary> /// 读取数据 /// </summary> private void ReadData() { byte[] data = NetEncode.Decode(ref receiveCache); //说明数据保存成功 if(data != null) { NetModel item = NetSerilizer.DeSerialize(data); UnityEngine.Debug.Log(item.Message); if(receiveCallBack != null) { receiveCallBack(item); } //尾递归,继续读取数据 ReadData(); } else { isReceiving = false; } } /// <summary> /// 服务器发送消息给客户端 /// </summary> public 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); } UnityEngine.Debug.Log("发送成功!"); Send (); } catch (Exception ex) { UnityEngine.Debug.Log(ex.ToString()); } } public void WriteSendDate(byte[] data){ sendCache.Enqueue(data); if(!isSending) { isSending = true; Send(); } } }
相关文章推荐
- 基于ProtoBuf协议实现网络传输(二)
- 基于ProtoBuf协议实现网络传输(一)
- ProtoBuf(protocol buffer) 网络传输协议
- App网络传输协议 xml json protobuf
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:8.自定义传输协议
- App网络传输协议(Json、XML、protobuf)
- 在 Android 的 IM 应用中使用 asmack 库实现用户头像的传输(基于VCard协议)
- 一种自动反射消息类型的 Google Protobuf 网络传输方案
- 一种自动反射消息类型的 Google Protobuf 网络传输方案
- 参照protobuf,将json数据转换成二进制在网络中传输。
- 【计算机网络常见面试题】实现可靠传输的协议
- 基于序列化技术(Protobuf)的socket文件传输
- 在 Android 的 IM 应用中使用 asmack 库实现用户头像的传输(基于VCard协议)
- 基于protobuf的RPC实现
- 一种自动反射消息类型的 Google Protobuf 网络传输方案
- 用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC).doc
- 一种自动反射消息类型的 Google Protobuf 网络传输方案
- 用Java实现基于SOAP的XML文档网络传输及远程过程调用(RPC)
- 网络通信Socket+Protobuf协议
- 一种基于Qt的可伸缩的全异步C/S架构服务器实现(二) 网络传输