高效能、易於使用的網路庫在所有提供的拓撲上支援 16k+ 並發客戶端。
專為 LAN 或 Internet 上的分散式即時並發應用程式而設計。
提供高吞吐量訊息傳遞、P2P、Nat Traversal、Reliable Udp 的基礎架構。
此儲存庫由主要核心元件和幾個特定於序列化的子元件組成。
請查看 Wiki 頁面以取得詳細文件。
網路庫,包括與網路系統相關的所有邏輯,從原始位元組到 P2P 大廳等抽象。它提供了可與任何類型的序列化一起使用的通用模板。
即插即用高效能模型,使用原始位元組。也用作更高級別模型的基礎。
Tcp Server/Client model
,位元組可以像常規套接字一樣分段。Tcp Byte Message Server/Client
,其中位元組以 4 位元組長度標頭傳送。它確保原子訊息傳遞而沒有碎片。Udp Server/Client
udp 系統,其中模擬伺服器並優化效能。Reliable Udp Client/Server
,其中現代 TCP 協定是透過 Udp 實現的。涉及可以與任何序列化協議一起使用的通用模型。
Generic Message Server/Client
設計用於自動發送和接收序列化訊息。Generic MessageProtocol Server/client
與上方類似,但新增了「MessageEnvelope」載體類,用作標頭/元資料。P2P Relay Client/Server
,Peers(客戶端)透過中繼伺服器發現彼此,可以使用 Udp/Rudp/Tcp 進行通訊。支援Tcp&Udp打孔。P2P Room/Lobby Server/Client
Relay 模型的擴展,其中同行可以定義房間,類似於遊戲配對伺服器。庫已使用作業系統 (Windows) 支援的盡可能多的客戶端進行了測試(大約 16k 動態連接埠)。包括 RUDP 在內的數據可靠性透過互聯網進行了廣泛測試。 Nat Traversal Udp 打洞技術也在網路上進行了測試並取得了成功。
注意:Libary 具有不安全的程式碼和堆疊記憶體分配。不安全部分經過充分測試,不會發生變更。
主裝配中的通用模型是使用特定的序列化器來實現的。所有方法簽名和用法都是相同的。它包括:
Nuget 套件可用:
核心網路函式庫 | 原始緩衝區 | 訊息包 | 網路序列化器 | 傑森 |
---|---|---|---|---|
Infinite Echo 基準測試是透過向伺服器發送一組訊息並取得回顯回應來完成的。每個回應都會引發新的請求。每個伺服器回應計為 1 個 Echo。
每條 1000 個種子訊息(32 位元組訊息 + 4 個標頭):
AMD 銳龍 7 5800H 筆記型電腦
客戶數量 | 每秒 TCP 回顯 | SSL 每秒回顯 |
---|---|---|
100 | 53,400,000 | 41,600,000 |
1000 | 43,600,000 | 22,200,000 |
5000 | 43,400,000 | 21,800,000 |
10000 | 42,800,000 | 21,700,000 |
英特爾 i9 13980HX 筆記型電腦
客戶數量 | 每秒 TCP 回顯 | SSL 每秒回顯 |
---|---|---|
100 | 128,800,000 | 79,400,000 |
1000 | 110,400,000 | 72,100,000 |
5000 | 102,100,000 | 67,500,000 |
10000 | 100,500,000 | 65,500,000 |
1000 個種子訊息信封(32 位元組有效負載,總共 48 位元組):
AMD 銳龍 7 5800H 筆記型電腦
客戶數量 | Protobuf 每秒回波 | 每秒安全的 Protobuf 回顯 |
---|---|---|
100 | 9,440,000 | 8,050,000 |
1000 | 8,780,000 | 7,480,000 |
5000 | 8,360,000 | 7,390,000 |
10000 | 8,340,000 | 7,350,000 |
英特爾 i9 13980HX 筆記型電腦
客戶數量 | Protobuf 每秒回波 | 每秒安全的 Protobuf 回顯 |
---|---|---|
100 | 31,200,000 | 20,650,000 |
1000 | 30,500,000 | 19,500,000 |
5000 | 28,200,000 | 17,650,000 |
10000 | 26,400,000 | 16,000,000 |
此基準測試僅發送具有原始位元組有效負載的訊息信封。序列化具體性能請參考:SerializationBenchmarks
有關詳細信息,請查看 AsyncTcpClient/Server 和 ByteMessageTcpClient/Server
位元組數組或數組段的任何區塊都將到達目的地而不會產生碎片。
private static void ExampleByteMessage ( )
{
ByteMessageTcpServer server = new ByteMessageTcpServer ( 20008 ) ;
server . OnBytesReceived += ServerBytesReceived ;
server . StartServer ( ) ;
ByteMessageTcpClient client = new ByteMessageTcpClient ( ) ;
client . OnBytesReceived += ClientBytesReceived ;
client . Connect ( "127.0.0.1" , 20008 ) ;
client . SendAsync ( Encoding . UTF8 . GetBytes ( "Hello I'm a client!" ) ) ;
void ServerBytesReceived ( Guid clientId , byte [ ] bytes , int offset , int count )
{
Console . WriteLine ( Encoding . UTF8 . GetString ( bytes , offset , count ) ) ;
server . SendBytesToClient ( clientId , Encoding . UTF8 . GetBytes ( "Hello I'm the server" ) ) ;
}
void ClientBytesReceived ( byte [ ] bytes , int offset , int count )
{
Console . WriteLine ( Encoding . UTF8 . GetString ( bytes , offset , count ) ) ;
}
}
output:
Hello I'm a client!
Hello I'm the server
注意:這裡重要的效能設定是使用緩衝區還是佇列作為緩衝策略。如果訊息主要是 byte[] 區域,例如(緩衝區、偏移量、計數),則使用 Buffer。如果訊息是完整位元組[](0 到結束),則使用佇列。
client . GatherConfig = ScatterGatherConfig . UseQueue ;
server . GatherConfig = ScatterGatherConfig . UseBuffer ;
對於 SSL 變體,差異是:
var ccert = new X509Certificate2 ( "client.pfx" , "greenpass" ) ;
// null certificate or default constructor will generate self signed certificate
client = new SslByteMessageClient ( ccert ) ;
var scert = new X509Certificate2 ( "server.pfx" , "greenpass" ) ;
// null certificate or default constructor will generate self signed certificate
server = new SslByteMessageServer ( 8888 , scert ) ;
// You can override the SSL cerificate validation callback
server . RemoteCertificateValidationCallback += .. .
client . RemoteCertificateValidationCallback += .. .
有關更多信息,請查看 SSLClient/Server 和 SSLByteMessageClient/Server
傳輸原始位元組的基本伺服器/客戶端。方法和回調簽名與位元組訊息模型相同。沒有透過基本伺服器/客戶端實現的協議,因此位元組可能會根據您的 MTU 大小而分段。
AsyncTcpServer server = new AsyncTcpServer ( port : 20000 ) ;
AsyncTpcClient client = new AsyncTpcClient ( ) ;
// SSL variant
// null certificate or default constructor will generate self signed certificate
var ccert = new X509Certificate2 ( "client.pfx" , "greenpass" ) ;
var scert = new X509Certificate2 ( "server.pfx" , "greenpass" ) ;
SslServer server = new SslServer ( 2000 , scert ) ;
SslClient client = new SslClient ( ccert ) ;
序列化網路是核心庫提供的通用類別的實現,它適用於所有序列化協定。
欲了解更多資訊:序列化網絡Examples here is only given for Protobuf-net, but signature is identical for any other provided serialization protocol(MessagePack, Json etc)
。
實現伺服器客戶端模型,其中序列化訊息以原子方式傳輸。聲明你的類型:
[ ProtoContract ]
class SampleMessage
{
[ ProtoMember ( 1 ) ]
public string sample ;
}
PureProtoServer server = new PureProtoServer ( 11234 ) ;
server . StartServer ( ) ;
server . BytesReceived += ( clientId , bytes , offset , count ) =>
{
SampleMessage msg = server . Serializer . Deserialize < SampleMessage > ( bytes , offset , count ) ;
Console . WriteLine ( msg . sample ) ;
msg . sample = "Jesse Lets cook" ;
server . SendAsync ( clientId , msg ) ;
} ;
PureProtoClient client = new PureProtoClient ( ) ;
client . Connect ( "127.0.0.1" , 11234 ) ;
client . BytesReceived += ( bytes , offset , count ) =>
{
SampleMessage msg = client . Serializer . Deserialize < SampleMessage > ( bytes , offset , count ) ;
Console . WriteLine ( msg . sample ) ;
} ;
client . SendAsync ( new SampleMessage ( ) { sample = "Yo! Mr White" } ) ;
訊息協定的實作是為了使用標準標頭包裝所有動態訊息類型。詳細解釋請參考訊息協議。
您可以聲明有效負載類型,即任何可使用 protobuf 序列化的類型。
[ ProtoContract ]
class SamplePayload : IProtoMessage
{
[ ProtoMember ( 1 ) ]
public string sample ;
}
安全變體範例:
private static async Task ExampleProtoSecure ( )
{
// null certificate or default constructor will generate self signed certificate
var scert = new X509Certificate2 ( "server.pfx" , "greenpass" ) ;
var cert = new X509Certificate2 ( "client.pfx" , "greenpass" ) ;
SecureProtoMessageServer server = new SecureProtoMessageServer ( 20008 , scert ) ;
server . StartServer ( ) ;
server . OnMessageReceived += ServerMessageReceived ;
var client = new SecureProtoMessageClient ( cert ) ;
client . OnMessageReceived += ClientMessageReceived ;
client . Connect ( "127.0.0.1" , 20008 ) ;
var Payload = new SamplePayload ( ) { sample = "Hello" } ;
var messageEnvelope = new MessageEnvelope ( ) ;
messageEnvelope . Header = "PayloadTest" ;
// You can just send a message, get replies on ClientMessageReceived.
client . SendAsyncMessage ( messageEnvelope ) ;
client . SendAsyncMessage ( messageEnvelope , Payload ) ;
// Or you can wait for a reply async.
MessageEnvelope result = await client . SendMessageAndWaitResponse ( messageEnvelope , Payload ) ;
var payload = result . UnpackPayload < SamplePayload > ( ) ;
Console . WriteLine ( $ "Client Got Response { payload . sample } " ) ;
void ServerMessageReceived ( Guid clientId , MessageEnvelope message )
{
Console . WriteLine ( $ "Server Received message { message . Header } " ) ;
server . SendAsyncMessage ( clientId , message ) ;
}
void ClientMessageReceived ( MessageEnvelope message )
{
}
}
ProtoMessageServer
和ProtoMessageClient
有相同的簽名,但建構子不接受憑證這個模型是我個人在其他項目(例如 P2PVideocall 和多人星際戰鬥機遊戲)中使用的。基本上,您的網路中的某處有一個中繼伺服器,它可以充當 LAN 中的本機網路集線器和/或在啟用連接埠轉送的情況下開放來自網際網路的連線。
中繼客戶端(對等點)連接到中繼伺服器並取得有關其他對等點存在的通知。對等點可以透過中繼伺服器相互傳送訊息,也可以直接互相傳送訊息(Udp 打孔)。
查看P2P Fore詳細信息
伺服器是完全被動的,允許其他對等點發現並向對方發送訊息。此外,還提供了 UDP 打洞等 NAT 穿越方法,以允許透過 Internet 或 LAN 進行直接通訊(到目前為止僅限 UDP,但我們有可靠的 udp)。
Relay Server Is Serialization Agnostic
這意味著任何序列化網路對等體(Protobuff、MessagePack 等)都可以使用相同的中繼伺服器。
要使用中繼伺服器,只需將您的伺服器聲明為:
var scert = new X509Certificate2 ( "server.pfx" , "greenpass" ) ;
var server = new SecureProtoRelayServer ( 20010 , scert ) ;
server . StartServer ( ) ;
中繼伺服器已預先設定。
中繼客戶端是實現應用程式邏輯的地方。您可以透過 Web 用戶端應用程式來發現彼此並進行交談。
要取消客戶端:
// null certificate or default constructor will generate self signed certificate
var cert = new X509Certificate2 ( "client.pfx" , "greenpass" ) ;
var client = new RelayClient ( cert ) ;
client . OnPeerRegistered += ( Guid peerId ) => ..
client . OnPeerUnregistered += ( Guid peerId ) => ..
client . OnMessageReceived += ( MessageEnvelope message ) => ..
client . OnUdpMessageReceived += ( MessageEnvelope message ) => ..
client . OnDisconnected += ( ) => ..
client . Connect ( "127.0.0.1" , 20010 ) ;
方法簽章和回呼與原始客戶端/伺服器模型相同(也帶有有效負載)。唯一的差異是您必須指定目標對等 Guid Id。每當新的對等點連接到中繼伺服器時,它來自 OnPeerRegistered 事件。中繼伺服器保證當前對等點集的同步以及所有對等點之間的最終一致性。因此,新的對等點將接收來自此事件的所有其他連接的對等點,而舊的對等點將收到更新。
client . SendAsyncMessage ( destinationPeerId , new MessageEnvelope ( ) { Header = "Hello" } ) ;
client . SendUdpMesssage ( destinationPeerId , new MessageEnvelope ( ) { Header = "Hello" } ) ;
// Or with an async reply
MessageEnvelope response = await client . SendRequestAndWaitResponse ( destinationPeerId ,
new MessageEnvelope ( ) { Header = "Who Are You?" } ) ;
Udp 訊息可以超過 65,527 位元組的資料封包限制。系統將大型 udp 訊息偵測為巨型訊息並以區塊的形式發送它們。接收端將嘗試重建訊息。如果所有部分未在逾時內到達,則訊息將被丟棄。 udp 的最大訊息大小為 16,256,000 位元組。
可靠的 udp 協定使用透過 UDP 實現的 TCP 演算法。
client . SendRudpMessage ( peerId , envelope ) ;
client . SendRudpMessage ( peerId , envelope , innerMessage ) ;
client . SendRudpMessageAndWaitResponse ( peerId , envelope , innerMessage ) ;
client . SendRudpMessageAndWaitResponse ( peerId , envelope ) ;
Nat 遍歷/打孔支援:
// Udp
bool result = await client . RequestHolePunchAsync ( destinationPeerId , timeOut : 10000 ) ;
// Tcp
bool result = await client . RequestTcpHolePunchAsync ( destinationPeerId , timeOut : 10000 ) ;
如果成功,它將允許您在當前和目標對等點之間發送直接 udp 訊息,以獲取雙向的其餘 udp 訊息。
這是中繼伺服器/客戶端的擴充。新增的是房間系統,同伴可以在其中建立或加入房間、查詢可用房間、向房間發送訊息(多播)。另外,保持相同的訊息系統在對等點之間發送 1-1 訊息。
您可以加入多個房間
Room Server Is Serialization Agnostic
這意味著任何序列化網路對等點(Protobuf、MessagePack 等)都可以使用相同的 Room 伺服器。
伺服器和客戶端的解密
var server = new SecureProtoRoomServer ( 20010 , scert ) ;
server . StartServer ( ) ;
var client1 = new SecureProtoRoomClient ( cert ) ;
簡單地創建/加入和離開房間:
client1 . CreateOrJoinRoom ( "Kitchen" ) ;
client1 . LeaveRoom ( "Kitchen" ) ;
房間回調如下。只有當您位於同一房間時才會觸發此回調。
client1 . OnPeerJoinedRoom += ( roomName , peerId ) => ..
client1 . OnPeerLeftRoom += ( roomName , peerId ) => ..
client1 . OnPeerDisconnected += ( peerId ) => ..
除了標準的 1-1 訊息回調之外,我們還有房間訊息回調。
client1 . OnTcpRoomMesssageReceived += ( roomName , message ) => ..
client1 . OnUdpRoomMesssageReceived += ( roomName , message ) => ..
client1 . OnTcpMessageReceived += ( message ) => ..
client1 . OnUdpMessageReceived += ( message ) => ..
所有安全 TCP 變體都採用 TLS 身份驗證/驗證來實現標準 SSL 套接字。欲了解更多信息,請查看:安全