Unity幾種socket通訊協議比較

2021-09-22 18:16:20 字數 2092 閱讀 9055

做unity專案 使用c#的socket與伺服器進行通訊時,訊息的解析有多種方案,比如protobuffer、marshal、或bindaryreader/bindarywriter等,但各有優缺點,再考慮到加/解密、壓縮與解壓縮、跨平台,最終還要考慮效能,其實最合適的方案只有乙個。

c#提供了兩種方式的連線、收發資料的方式,一種是同步處理,一種是非同步處理。

同步處理方式,需要自己使用多執行緒進行處理。連線時需要啟動乙個執行緒,發訊息時啟動乙個執行緒,收訊息啟動乙個執行緒。這樣更可控,但如果經驗不足,也容易出bug,再者unity(mono)對執行緒的支援並不那麼完美(可能出現執行緒掛起後,無法恢復),導致致命bug。

非同步處理,可以減少對執行緒的依賴,建議使用這種方式。

關於連線的處理,這裡暫時不細述。

protobuffer是個很好的方式,提供了一套完整的解決方案,有描述檔案,有轉換工具,多語言支援,使用簡單,易於維護。

但protobuf效能損耗比較高,對於通訊量大且頻繁的遊戲,就不太適用。

而且處理加密/解密、壓縮/解壓時,還要做額外的處理,並且累加了效能消耗,使效能降到不可接受的範圍。

c/c++在序列化或反序列化記憶體二進位制資料時,相對比較容易,大部門情況下,只需對記憶體塊和struct進行操作即可,無需編碼太多解析**。使用marshal就是型別這種方,反序列過程是從託管記憶體傳byte與struct進去,返回反序列好的struct對像;序列化過程是把struct物件傳入非託管記憶體,轉化為byte。

這種方式,實現起來也相對比較容易,解析效能比較高,特別是對比較大且複雜的訊息。但託管記憶體與非託管記憶體的轉換過程,會產生相應大小的臨時物件,在unity中會觸發gc,導致效能折半。

乙個致命的問題,如果結構中含有陣列,會觸發jit,ios系統只允許aot,所以一但需要處理陣列(非值型別的字段)在ios上就會直接crash。

因此,這種方式並不是乙個好的選擇,更不是通用的選擇。

在c#的system.io命名空間下,有binaryreader與binarywriter兩個類,分別處理對memeorystream的讀寫。

我們從socket中接收到byte後,通過種方式按讀出每個字段,實現反序列化:

const

int max_buffer_size = 1024;

byte datafromsocket = new

byte[max_buffer_size];

memorystream ms = new

memorystream();

binaryreader br = new

binaryreader(ms);

ms.write(datafromsocket, 0, max_buffer_size);

br.readint16();

br.readboolean();

br.readchars(10);

....

把c#物件,按順序寫入欄位的值,實現序列化生成byte,並傳給socket傳送出去:

memorystream bwms = new

memorystream(max_buffer_size);

binarywriter bw = new

binarywriter(bwms);

bw.write(0);//有很多過載,可以支援很多資料型別的寫入

...bwms.toarray();//轉化為byte,通過socket傳送

這種方式需要按照欄位的順序進行讀取或寫入,如果是通過程式設計師手動去寫,工作量相當大的,面且很維護,增/刪字段簡直會讓人崩潰,面且非常容易出錯。

然而,我們可以通過編寫乙個工具,把protobuffer的訊息定義檔案(或別的定義方式)轉化為有序的讀/寫**,就像protobuffer生成的類檔案一樣。

這種方式,相比前兩種,效能是最好,不但讀/寫方便,而且可以控制中間臨時記憶體的建立數量(可使用物件池),大大減少unity的gc。

目前我現在的專案主要使用這種方式,並開發了相應的工具。

lua也有多種方式來解析socket二進位制訊息,比如逐字段解析、或使用protobuffer(protoc-gen-lua)等。

逐字段解析需要自己開發工具,並編寫解析**,目前沒採用。

對與unity的socket通訊,還有非常多的細節,這裡暫未提及

C 程序間通訊的幾種方式 Socket通訊

方式二 socket通訊 套接字 socket 是支援tcp ip協議 安全 和udp協議 快速 的網路通訊的基本操作單元。套接字包含進行網路通訊必須的五種資訊 連線使用的協議,本地主機的ip位址,本地程序的協議埠,遠地主機的ip位址,遠地程序的協議埠。為了滿足不同程式對通訊質量和效能的要求,一般的...

Unity如何實現網路通訊(二) SOCKET

強聯網在我們的遊戲開發中所佔比重越來越大,尤其是開發mmo遊戲時,更需要強聯網來進行實時更新,所以我們就有了強聯網的需要。首先我們得清楚強聯網的工作原理,說到強聯網,我們就必須說到socket。socket是對tcp ip協議的封裝和應用,是面向程式設計師的,給我們提供了操作網路的介面,但是我們也必...

Unity3d網路遊戲Socket通訊

下面是unity3d遊戲通訊socket實現 basegamesocket.cs 原創 dongfu.luo using system using system.collections.generic using system.net.sockets public abstract class ba...