2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

Unity技術(shù)博客

 kiki的號 2017-07-22

Unity版本: 5.3

使用語言: C#


寫在前面

ProtoBuf是Google公司推出的一種二進制序列化工具,適用于數(shù)據(jù)的網(wǎng)絡傳輸。
基于Socket實現(xiàn)時時通信,關(guān)于數(shù)據(jù)粘包的編碼和解碼處理是必不可少的。


實現(xiàn)功能:

   1.基于ProtoBuf序列化對象
   2.使用Socket實現(xiàn)時時通信
   3.數(shù)據(jù)包的編碼和解碼

3.數(shù)據(jù)包的編碼和解碼

首先,舉個例子,這個月信用卡被媳婦刷爆了,面對房貸車貸的壓力,我只能選擇分期付款。。。

那么OK了,現(xiàn)在我想問一下,當服務器向客戶端發(fā)送的數(shù)據(jù)過大時怎么辦呢?

當服務器需要向客戶端發(fā)送一條很長的數(shù)據(jù),也會“分期付款!”,服務器會把一條很長的數(shù)據(jù)分成若干條小數(shù)據(jù),多次發(fā)送給客戶端。

可是,這樣就又有另外一個問題,客戶端接受到多條數(shù)據(jù)之后如何解析?

這里其實就是客戶端的解碼。server發(fā)數(shù)據(jù)一般采用“長度+內(nèi)容”的格式,Client接收到數(shù)據(jù)之后,先提取出長度來,然后根據(jù)長度判斷內(nèi)容是否發(fā)送完畢。

再次重申,用戶在發(fā)送序列化好的消息的前,需要先編碼后再發(fā)送消息;用戶在接受消息后,需要解碼之后再解析數(shù)據(jù)(反序列化)。

using UnityEngine;
using System.Collections.Generic;
using System.IO;

/// <summary>
/// 編碼和解碼
/// </summary>
public class NetEncode {

    /// <summary>
    /// 將數(shù)據(jù)編碼 長度+內(nèi)容
    /// </summary>
    /// <param name="data">內(nèi)容</param>
    public static byte[] Encode(byte[] data)
    {
        //整形占四個字節(jié),所以聲明一個+4的數(shù)組
        byte[] result = new byte[data.Length + 4];
        //使用流將編碼寫二進制
        MemoryStream ms = new MemoryStream();
        BinaryWriter br = new BinaryWriter(ms);
        br.Write(data.Length);
        br.Write(data);
        //將流中的內(nèi)容復制到數(shù)組中
        System.Buffer.BlockCopy(ms.ToArray(), 0, result, 0, (int)ms.Length);
        br.Close();
        ms.Close();
        return result;
    }

    /// <summary>
    /// 將數(shù)據(jù)解碼
    /// </summary>
    /// <param name="cache">消息隊列</param>
    public static byte[] Decode(ref List<byte> cache)
    {
        //首先要獲取長度,整形4個字節(jié),如果字節(jié)數(shù)不足4個字節(jié)
        if(cache.Count < 4)
        {
            return null;
        }
        //讀取數(shù)據(jù)
        MemoryStream ms = new MemoryStream(cache.ToArray());
        BinaryReader br = new BinaryReader(ms);
        int len = br.ReadInt32();
        //根據(jù)長度,判斷內(nèi)容是否傳遞完畢
        if(len > ms.Length - ms.Position)
        {
            return null;
        }
        //獲取數(shù)據(jù)
        byte[] result = br.ReadBytes(len);
        //清空消息池
        cache.Clear();
        //講剩余沒處理的消息存入消息池
        cache.AddRange(br.ReadBytes((int)ms.Length - (int)ms.Position));

        return result;
    }
}

用戶接受數(shù)據(jù)代碼如下:

using System;
using System.Collections.Generic;
using System.Net.Sockets;

/// <summary>
/// 表示一個客戶端
/// </summary>
public class NetUserToken {
    //連接客戶端的Socket
    public Socket socket;
    //用于存放接收數(shù)據(jù)
    public byte[] buffer;
    //每次接受和發(fā)送數(shù)據(jù)的大小
    private const int size = 1024;

    //接收數(shù)據(jù)池
    private List<byte> receiveCache;
    private bool isReceiving;
    //發(fā)送數(shù)據(jù)池
    private Queue<byte[]> sendCache;
    private bool isSending;

    //接收到消息之后的回調(diào)
    public Action<NetModel> receiveCallBack;


    public NetUserToken()
    {
        buffer = new byte[size];
        receiveCache = new List<byte>();
        sendCache = new Queue<byte[]>();
    }

    /// <summary>
    /// 服務器接受客戶端發(fā)送的消息
    /// </summary>
    /// <param name="data">Data.</param>
    public void Receive(byte[] data)
    {
        UnityEngine.Debug.Log("接收到數(shù)據(jù)");
        //將接收到的數(shù)據(jù)放入數(shù)據(jù)池中
        receiveCache.AddRange(data);
        //如果沒在讀數(shù)據(jù)
        if(!isReceiving)
        {
            isReceiving = true;
            ReadData();
        }
    }

    /// <summary>
    /// 讀取數(shù)據(jù)
    /// </summary>
    private void ReadData()
    {
        byte[] data = NetEncode.Decode(ref receiveCache);
        //說明數(shù)據(jù)保存成功
        if(data != null)
        {
            NetModel item = NetSerilizer.DeSerialize(data);
            UnityEngine.Debug.Log(item.Message);
            if(receiveCallBack != null)
            {
                receiveCallBack(item);
            }
            //尾遞歸,繼續(xù)讀取數(shù)據(jù)
            ReadData();
        }
        else
        {
            isReceiving = false;
        }
    }

    /// <summary>
    /// 服務器發(fā)送消息給客戶端
    /// </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("發(fā)送成功!");
            Send ();
        } catch (Exception ex) {
            UnityEngine.Debug.Log(ex.ToString());
        }
    }

    public void WriteSendDate(byte[] data){
        sendCache.Enqueue(data);
        if(!isSending)
        {
            isSending = true;
            Send();
        }
    }
}

寫在最后

 #成功的道路沒有捷徑,代碼這條路更是如此,唯有敲才是王道。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約