protobuf-net 的應用
https://blog.csdn.net/st02009/article/details/78742483?utm_source=blogxgwz7
protobuf-net 通常用於數據傳輸和excel數據的二進制化,是一個方便的工具
現在寫一個關於協議的protobuf-net的應用
**
0先將自動化的cmd代碼貼出來
**
set CSC20=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe
SET PROTO=protobuf\
mkdir proto
rmdir /s/q proto-build\code
mkdir proto-build\code
rmdir /s/q proto-build\dll
mkdir proto-build\dll
pushd proto
set protogenexe=..\protogen\protogen.exe
for %%p in (*.proto) do %protogenexe% -i:%%p -o:..\proto-build\code\%%~np.cs -ns:sg
popd
set proto_dll=proto-build\dll\mymodel.dll
%CSC20% /target:library /out:%proto_dll% /reference:protogen\protobuf-net.dll proto-build\code*.cs
serializer\serializer-builder.exe %cd%\%proto_dll% 70 proto-final\
pause
1首先獲取protobuf-net,這個網上不少,獲取一個
2自己編寫協議的格式,用txt,最後改後綴爲proto,
例子如下:
//副本列表請求
message Copy_List_Req{
required int32 roleID = 1; //玩家ID
required int32 battleID = 2; //戰役ID
}
3用protogen.exe 將2的文本協議轉化成對應的cs文件,具體代碼是(這是一個批處理針對多個proto文本文件)
“`
set protogenexe=..\protogen\protogen.exe
for %%p in (*.proto) do %protogenexe% -i:%%p -o:..\proto-build\code\%%~np.cs -ns:sg
4,將上面生成的所有cs文件轉換成一個dll文件
------------------------
1
2
3
4
set proto_dll=proto-build\dll\mymodel.dll
%CSC20% /target:library /out:%proto_dll% /reference:protogen\protobuf-net.dll proto-build\code*.cs
5,
**
將上面生成的dll文件序列化成二進制且每70個proto分割成一個新的dll,cmd裏對應的代碼是
-------------------------------------------------
**
serializer\serializer-builder.exe %cd%\%proto_dll% 70 proto-final\
其中 serialize代碼是
1
2
3
4
5
6
7
8
9
10
11
12
using System;
using System.IO;
namespace mw_serializer_builder
{
class Program
{
static void Main(string[] args)
{
string path = args[0];
Console.WriteLine(path);
FileInfo info = new FileInfo(path);
string modelFileName = Path.GetFileNameWithoutExtension(path);
var ass = System.Reflection.Assembly.LoadFile(path);
var types = ass.GetTypes();
var tm = ProtoBuf.Meta.TypeModel.Create();
int split = int.Parse(args[1]);
string outPath = args[2];
int c = 0;
int i = 0;
foreach(var t in types)
{
if(t.Name.EndsWith("_ValidateInfo"))
{
continue;
}
tm.Add(t, true);
i++;
if (i > split)
{
string serializens = modelFileName + "-serializer-" + c.ToString();
string serializername = serializens + ".dll";
tm.Compile(serializens.Replace("-", "_"), serializername );
File.Copy(serializername ,outPath + serializername,true);
File.Delete(serializername );
Console.WriteLine(serializername);
c++;
tm = ProtoBuf.Meta.TypeModel.Create();
i = 0;
}
}
if (i > 0)
{
string serializens = modelFileName + "-serializer-" + c.ToString();
string serializername = serializens + ".dll";
tm.Compile(serializens.Replace("-", "_"), serializername);
File.Copy(serializername , outPath + serializername,true);
File.Delete(serializername );
Console.WriteLine(serializername);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
}
6.上面的一切是爲了解析從服務器發來的數據,一般服務器的發來的二進制數據前一個或2個字節解析出來的整數經過客戶端事先存好的映射關係取得type,就是反序列化需要的類的類型獲得最終可用的結構
代碼如下
1
2
3
4
static Packet Parse(int pt, Stream stm)
{
if (pt == (int)PacketTypeS2C.LS2C_LOGIN)
{
mw.LoginReturn lr = m_serializer.Deserialize(stm, null, typeof(mw.LoginReturn)) as mw.LoginReturn;
return new Packet(pt, lr);
}
.......
.......
}
1
2
3
4
5
6
7
8
在實例化協議類的時候可以加上特性custom attribute,然後寫一個方法統一處理這些特性如`[PacketHandlerAttribute(PacketOpcode.CHANNEL_AND_VERSION_REQ,typeof(sg.LS2C_Channel_And_Version_Res))]
public void RequestCheckChannelAndVersion(string channelId,string versionNum,NetManager.RevCallBackWithPacket del) {
Packet pak = new Packet();
sg.C2LS_Channel_And_Version_Req req = new sg.C2LS_Channel_And_Version_Req();
req.channelId = channelId;
req.versionNum = versionNum;
pak.data = req;
pak.opcode = PacketOpcode.CHANNEL_AND_VERSION_REQ;
LSNetManager.Instance.SendPacket(pak,del);
}`
統一管理的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
protected void RegisterPacketHandler(object obj) {
var methods = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach(var method in methods) {
PacketHandlerAttribute[] attributes = method.GetCustomAttributes(typeof(PacketHandlerAttribute),false) as PacketHandlerAttribute[];
if(attributes.Length == 0)
continue;
try {
foreach(var attribute in attributes) {
if(obj is NetReceiver) {
var handlerDelegate = (HandlePacketDelegate)Delegate.CreateDelegate(typeof(HandlePacketDelegate),obj,method);
RegisterReceiveDelegate(attribute.PacketOpcodeID,handlerDelegate);
}
if(!packetReflections.ContainsKey(attribute.PacketOpcodeID)) {
packetReflections.Add(attribute.PacketOpcodeID,attribute.HandlerType);
}
}
} catch(Exception e) {
var handlerStr = obj.GetType().FullName + “.” + method.Name;
throw new Exception(“Unable to register PacketHandler ” + handlerStr + “.\n” + e.Message);
}
}
}
“`這樣通過數字轉換成enum,通過enum對應type,通過type用上面的已經二進制化的dll反序列化二進制獲取object
發送數據的時候就簡單了,直接序列化就好了
————————————————
版權聲明:本文爲CSDN博主「st02009」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/st02009/article/details/78742483