【Unity】 在Unity中實現Tcp通訊(3)—— ProtoBuf

通過上兩篇內容

https://blog.csdn.net/s_GQY/article/details/106187350

https://blog.csdn.net/s_GQY/article/details/106192109

服務端和客戶端的通訊已經實現了。

但是,在之前的通訊中是直接使用了字符串來進行數據的傳輸。

而在實際開發當中,要傳輸的數據結構是非常的複雜的,僅僅使用字符串勢必無法滿足基本的開發需求。

於是,本篇將來闡述一下Tcp網絡通訊中常用的序列化工具,ProtoBuf。

 

ProtoBuf是Google研發的一種數據序列化工具,它使用Tag技術使數據在序列化成byte時變得非常的小,解析速度也是非常的快,所以很多軟件、遊戲的網絡通訊部分通常都會採用Protobuf來進行數據的傳輸。

關於Tag技術及Protobuf原理這裏不做過多的闡述,有興趣可以看這篇文章

下面開始進行protobuf相關的講解。

 

一.安裝使用protobuf以及生成CSharp代碼

1.安裝 Python

下載python27,安裝並添加系統變量

在命令行執行"python" 命令,出現下圖表示安裝成功

 

 

2.安裝Protobuf

先在這裏下載protobuf,這是一個編譯好的發佈版本,如果想自己編譯就下載源碼即可,我用得是2.5.0

在目錄protobuf-2.5.0\python進入命令行,執行命令"python setup.py install"(進入到python路徑然後shift+右鍵打開命令行即可)

出現下圖則安裝成功

 

3.下載Protobuf Net編譯proto gen

這裏下載Protobuf Net的源碼,分別編譯ProtoGen,precompile,protobuf-net這3個工程

 

將得到這些文件,把它們拷出來,放到和protobuf同級目錄下,這裏放到了proto-gen-cs目錄下

 

由於這個下載地址下載速度堪憂,這裏給出編譯好的版本,直接下載使用即可

 

4.編寫bat程序,批量轉換.proto文件

在protobuf同級目錄下創建一個空的txt,將其重命名爲buildcs.bat(名字隨意),如圖

然後bat文件內輸入這麼一行代碼,保存

@echo off

set Path=proto-gen-cs\protogen.exe

for /f "delims=" %%i in ('dir  /b Proto "proto/*.proto"') do %Path% -i:proto/%%i -o:cs/%%~ni.cs

pause

 

proto文件夾下創建測試proto協議,新建一個空txt,重命名爲test.proto

使用pad++或者sublime之類的編輯器打開它,輸入如下代碼

package client;

message test {
    optional string content = 1;                    //name
}

這裏如果不瞭解proto協議如何編寫可以看這篇文章

 

雙擊buildcs.bat不出以爲,會在cs文件夾下得到一個轉換後的csharp代碼,長這個樣子


 

二.使用生成的代碼序列化數據,進行Tcp通訊

有了proto的代碼,就可以將其導入到項目中使用。

1.客戶端:

把protobuf-net.dll拖入到unity的plugins文件夾下,把生成的test.cs拖入到unity的scripts文件夾下

先封裝一個工具類,它用於序列化和反序列化數據

using System;
using ProtoBuf;
using System.IO;


public class ProtoBufUtil
{
    public static byte[] ObjectToBytes<T>(T instance)
    {
        try
        {
            byte[] array;
            if (instance == null)
            {
                array = new byte[0];
            }
            else
            {
                MemoryStream memoryStream = new MemoryStream();
                Serializer.Serialize(memoryStream, instance);
                array = new byte[memoryStream.Length];
                memoryStream.Position = 0L;
                memoryStream.Read(array, 0, array.Length);
                memoryStream.Dispose();
            }

            return array;

        }
        catch (Exception ex)
        {

            return new byte[0];
        }
    }

    public static T BytesToObject<T>(byte[] bytesData, int offset, int length)
    {
        if (bytesData.Length == 0)
        {
            return default(T);
        }
        try
        {
            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Write(bytesData, 0, bytesData.Length);
            memoryStream.Position = 0L;
            T result = Serializer.Deserialize<T>(memoryStream);
            memoryStream.Dispose();
            return result;
        }
        catch (Exception ex)
        {
            return default(T);
        }
    }
}

然後把在第二篇博客客中的客戶端發送數據的代碼改一下

private void onClick()
{
        if(!SocketMgr.Instance.IsConnected)
	{
            SocketMgr.Instance.Connect("127.0.0.1", 8888);
	    return;
	}

	client.test sendContent = new client.test();//創建protobuf序列化實例
	sendContent.content = inputField.text;//對應字段賦值
	byte[] buffer = ProtoBufUtil.ObjectToBytes<test>(sendContent);//序列化
	SocketMgr.Instance.Send(1, buffer);//發送
}

到這裏,只要點擊按鈕,客戶端會把數據序列化成protobuf的格式併發送到服務端

2.服務端:

添加對protobuf-net.dll(就是上面提到的那個protobuf-net.dll文件)的引用

把客戶端的ProtobufUtil拖到服務端工程目錄下,再把test.cs到也拖到工程目錄下

然後把在第二篇博客客中的服務端解析數據的代碼改一下

private void CheckReceiveBuffer(object state)
{
    lock (m_ReceiveQueue)
    {
        if (m_ReceiveQueue.Count < 1) return;
        byte[] buffer = m_ReceiveQueue.Dequeue();
        byte[] msgContent = new byte[buffer.Length - 2];
        ushort msgCode = 0;

        using (MemoryStream ms = new MemoryStream(buffer))
        {
            byte[] msgCodeBuffer = new byte[2];
            ms.Read(msgCodeBuffer, 0, msgCodeBuffer.Length);
            msgCode = BitConverter.ToUInt16(msgCodeBuffer, 0);
            ms.Read(msgContent, 0, msgContent.Length);
        }

        test content = ProtoBufUtil.BytesToObject<test>(msgContent, 0, msgContent.Length);//調用protobuf,把數據反序列化爲test對象
        Console.WriteLine("消息編號:" + msgCode + ",內容:" + content.content);
    }
}

到這裏服務端也順利的使用protobuf來解析數據了,下面開始測試

 

3.測試:

還是老套路,先啓動服務器,然後客戶端連接服務器,成功

 

然後客戶端輸入任意內容點擊發送

服務端成功的使用Protobuf解析了數據,啪啪啪,此處仍然要有掌聲雷動

 


 

三.結束

到這裏protobuf的安裝,使用就已經全部寫完了,下一篇就開始進行心跳機制的講解,各位再見!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章