通過上兩篇內容
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的安裝,使用就已經全部寫完了,下一篇就開始進行心跳機制的講解,各位再見!