Pustaka jaringan berkinerja tinggi dan mudah digunakan yang mendukung 16k+ klien bersamaan di semua topologi yang disediakan.
Dirancang untuk mendistribusikan aplikasi bersamaan secara realtime melalui LAN atau Internet.
Menyediakan infrastruktur untuk penyampaian pesan throughput tinggi, P2P, Nat Traversal, Udp yang Andal.
Repositori ini terdiri dari rakitan inti utama dan beberapa sub rakitan khusus serialisasi.
Silakan periksa halaman Wiki untuk dokumentasi rinci.
Perpustakaan Jaringan, Mencakup semua logika yang terkait dengan sistem jaringan, mulai dari byte mentah hingga abstraksi seperti lobi P2P. Ini menyediakan templat umum untuk digunakan dengan semua jenis serialisasi.
Plug&Play model berkinerja tinggi, bekerja dengan byte mentah. Juga digunakan sebagai dasar untuk model tingkat yang lebih tinggi.
Tcp Server/Client model
dengan buffering dinamis dan sub sistem antrian, byte dapat terfragmentasi seperti soket biasa.Tcp Byte Message Server/Client
tempat byte dikirim dengan header panjang 4 byte. Ini memastikan pengiriman pesan atom tanpa fragmentasi.Udp Server/Client
sistem udp tempat server ditiru dengan kinerja yang dioptimalkan.Reliable Udp Client/Server
tempat protokol TCP modern diimplementasikan melalui Udp.Melibatkan model generik yang dapat bekerja dengan protokol serialisasi apa pun.
Generic Message Server/Client
dirancang untuk mengirim dan menerima pesan serial secara atom.Generic MessageProtocol Server/client
serupa dengan di atas, tetapi dengan tambahan kelas pembawa "MessageEnvelope", digunakan sebagai header/metadata.P2P Relay Client/Server
tempat Rekan (Klien) menemukan satu sama lain melalui server Relai, dapat menggunakan Udp/Rudp/Tcp untuk berkomunikasi. Mendukung Lubang Pukulan Tcp & Udp.P2P Room/Lobby Server/Client
dari model Relai di mana rekan-rekan dapat menentukan ruangan, mirip dengan server perjodohan game.Perpustakaan diuji dengan klien sebanyak yang didukung OS (Windows) (sekitar 16 ribu port dinamis). Keandalan data termasuk RUDP diuji melalui internet secara ekstensif. Holepunching Nat Traversal Udp juga diuji melalui internet dengan sukses.
Catatan: Perpustakaan memiliki kode yang tidak aman dan alokasi memori tumpukan. Bagian yang tidak aman telah diuji dengan baik dan tidak dapat diubah.
Model generik dari perakitan utama diimplementasikan dengan serializer tertentu. Alasan pembagian ini adalah untuk menghindari ketergantungan yang tidak perlu. Semua tanda tangan dan penggunaan metode identik. Ini termasuk:
Tersedia Paket Nuget :
Perpustakaan Jaringan Inti | Protobuf | Paket Pesan | NetSeralizer | Jason |
---|---|---|---|---|
Tolok ukur Infinite Echo dilakukan dengan mengirimkan serangkaian pesan ke server dan mendapatkan respons gema. Setiap respons menyebabkan permintaan baru. Setiap respons server dihitung sebagai 1 Echo.
1000 pesan benih (pesan 32 byte + 4 header) masing-masing:
Laptop AMDRyzen 7 5800H
Jumlah Klien | TCP Gema per Detik | SSL Gema per Detik |
---|---|---|
100 | 53.400.000 | 41.600.000 |
1000 | 43.600.000 | 22.200.000 |
5000 | 43.400.000 | 21.800.000 |
10.000 | 42.800.000 | 21.700.000 |
Laptop Intel i9 13980HX
Jumlah Klien | TCP Gema per Detik | SSL Gema per Detik |
---|---|---|
100 | 128.800.000 | 79.400.000 |
1000 | 110.400.000 | 72.100.000 |
5000 | 102.100.000 | 67.500.000 |
10.000 | 100.500.000 | 65.500.000 |
1000 amplop pesan benih (payload 32 byte, total 48 byte):
Laptop AMDRyzen 7 5800H
Jumlah Klien | Protobuf Gema per Detik | Amankan Protobuf Echo per Detik |
---|---|---|
100 | 9.440.000 | 8.050.000 |
1000 | 8.780.000 | 7.480.000 |
5000 | 8.360.000 | 7.390.000 |
10.000 | 8.340.000 | 7.350.000 |
Laptop Intel i9 13980HX
Jumlah Klien | Protobuf Gema per Detik | Amankan Protobuf Echo per Detik |
---|---|---|
100 | 31.200.000 | 20.650.000 |
1000 | 30.500.000 | 19.500.000 |
5000 | 28.200.000 | 17.650.000 |
10.000 | 26.400.000 | 16.000.000 |
Tolok ukur ini hanya mengirimkan amplop pesan dengan payload byte mentah. Untuk kinerja spesifik serialisasi, silakan merujuk ke: SerializationBenchmarks
Untuk info detail Lihat AsyncTcpClient/Server dan ByteMessageTcpClient/Server
Setiap potongan array byte atau segmen array akan mencapai tujuan tanpa fragmentasi.
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
Catatan: Pengaturan performa yang penting di sini adalah apakah akan menggunakan buffer atau antrian sebagai kebijakan buffering. Gunakan Buffer jika pesan sebagian besar merupakan wilayah byte[] seperti (buffer, offset,count). Gunakan Antrian jika pesannya penuh byte[] (0 sampai akhir).
client . GatherConfig = ScatterGatherConfig . UseQueue ;
server . GatherConfig = ScatterGatherConfig . UseBuffer ;
Untuk varian SSL perbedaannya adalah:
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 += .. .
Untuk info lebih lanjut, periksa SSLClient/Server dan SSLByteMessageClient/Server
Server Basis/Klien tempat byte mentah ditransfer. Tanda tangan metode dan panggilan balik identik dengan model pesan byte. Tidak ada protokol yang diterapkan pada Server/Klien dasar, oleh karena itu byte mungkin terfragmentasi tergantung pada ukuran MTU Anda.
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 ) ;
Jaringan Berseri adalah implementasi kelas generik yang disediakan oleh Perpustakaan Inti. Ini berlaku untuk semua protokol serialisasi.
Untuk info lebih lanjut: Jaringan Berseri
Examples here is only given for Protobuf-net, but signature is identical for any other provided serialization protocol(MessagePack, Json etc)
.
Mengimplementasikan model klien server tempat pesan serial ditransfer secara atom. Nyatakan tipe Anda:
[ 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" } ) ;
Protokol pesan diimplementasikan untuk menggabungkan semua jenis pesan dinamis dengan header standar. Silakan merujuk ke Protokol Pesan untuk penjelasan rinci.
Anda dapat mendeklarasikan tipe payload Anda, yaitu tipe apa pun yang dapat diserialkan dengan protobuf.
[ ProtoContract ]
class SamplePayload : IProtoMessage
{
[ ProtoMember ( 1 ) ]
public string sample ;
}
Contoh untuk Varian Aman:
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
dan ProtoMessageClient
memiliki tanda tangan yang identik kecuali konstruktornya tidak mengambil sertifikat Model ini adalah apa yang saya gunakan secara pribadi pada proyek saya yang lain seperti P2PVideocall dan Multiplayer Starfighter Game. Pada dasarnya Anda memiliki server Relay di suatu tempat di jaringan Anda, yang dapat bertindak sebagai hub jaringan lokal di LAN dan/atau terbuka untuk koneksi dari internet jika penerusan porta diaktifkan.
Klien relai (Rekan) terhubung ke server Relai dan mendapat pemberitahuan tentang keberadaan rekan lainnya. Rekan dapat mengirim pesan satu sama lain melalui Relay Server, atau langsung ke satu sama lain (Udp holepunch).
Lihat info detail P2P Kedepan
Server sepenuhnya pasif, memungkinkan rekan-rekan lain untuk menemukan dan mengirim pesan satu sama lain. Selain itu metode traversal NAT seperti holepunching UDP disediakan untuk memungkinkan komunikasi langsung melalui Internet atau LAN (sejauh ini hanya UDP, tetapi kami memiliki udp yang dapat diandalkan).
Relay Server Is Serialization Agnostic
yang berarti semua Rekan jaringan serial, (Protobuff, MessagePack, dll) dapat menggunakan server relai yang sama.
Untuk menggunakan server Relay, cukup nyatakan server Anda sebagai:
var scert = new X509Certificate2 ( "server.pfx" , "greenpass" ) ;
var server = new SecureProtoRelayServer ( 20010 , scert ) ;
server . StartServer ( ) ;
Server relai sudah dikonfigurasi sebelumnya.
Klien relai adalah tempat logika aplikasi Anda diimplementasikan. Anda dapat membuat web aplikasi klien Anda untuk menemukan dan berbicara satu sama lain.
Untuk mendeklarasikan klien:
// 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 ) ;
Tanda tangan metode dan panggilan balik identik dengan model klien/server proto (juga dengan Payloads). Bedanya hanya Anda harus menentukan Guid Id rekan tujuan. Itu berasal dari acara OnPeerRegistered, setiap kali rekan baru terhubung ke server relai. Server Relai menjamin sinkronisasi kumpulan rekan saat ini dengan konsistensi akhir di antara semua rekan. Jadi rekan-rekan baru akan menerima semua rekan-rekan lain yang terhubung dari acara ini dan rekan-rekan lama akan menerima pembaruan.
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?" } ) ;
Pesan udp bisa lebih dari batas datagram yaitu 65.527 byte. Sistem mendeteksi pesan udp berukuran besar sebagai pesan Jumbo dan mengirimkannya dalam beberapa bagian. Menerima akhir dengan akan mencoba merekonstruksi pesan tersebut. jika semua bagian tidak tiba dalam batas waktu, pesan akan dihapus. Ukuran pesan maksimal untuk udp adalah 16.256.000 byte.
Protokol udp yang andal digunakan sebagai algoritma TCP yang diimplementasikan melalui UDP.
client . SendRudpMessage ( peerId , envelope ) ;
client . SendRudpMessage ( peerId , envelope , innerMessage ) ;
client . SendRudpMessageAndWaitResponse ( peerId , envelope , innerMessage ) ;
client . SendRudpMessageAndWaitResponse ( peerId , envelope ) ;
Dukungan Nat Traversal/Holepunch:
// Udp
bool result = await client . RequestHolePunchAsync ( destinationPeerId , timeOut : 10000 ) ;
// Tcp
bool result = await client . RequestTcpHolePunchAsync ( destinationPeerId , timeOut : 10000 ) ;
jika berhasil, ini akan memungkinkan Anda mengirim pesan udp langsung antara rekan saat ini dan tujuan untuk pesan udp lainnya di kedua arah.
Ini adalah perpanjangan dari Relay Server/Klien. Penambahannya adalah sistem ruangan di mana rekan-rekan dapat membuat atau bergabung dengan ruangan, menanyakan ruangan yang tersedia, mengirim pesan ke ruangan (multicast). Selain itu menjaga sistem pesan yang sama untuk mengirim 1-1 pesan antar rekan.
Anda dapat bergabung dengan beberapa ruangan
Room Server Is Serialization Agnostic
yang berarti semua rekan jaringan serial, (Protobuf, MessagePack, dll) dapat menggunakan server Room yang sama.
Deklarasi Server dan klien
var server = new SecureProtoRoomServer ( 20010 , scert ) ;
server . StartServer ( ) ;
var client1 = new SecureProtoRoomClient ( cert ) ;
Untuk membuat/bergabung dan keluar dari ruangan cukup:
client1 . CreateOrJoinRoom ( "Kitchen" ) ;
client1 . LeaveRoom ( "Kitchen" ) ;
Panggilan balik ruangan adalah sebagai berikut. Panggilan balik ini hanya terpicu jika Anda berada di ruangan yang sama.
client1 . OnPeerJoinedRoom += ( roomName , peerId ) => ..
client1 . OnPeerLeftRoom += ( roomName , peerId ) => ..
client1 . OnPeerDisconnected += ( peerId ) => ..
Selain panggilan balik pesan 1-1 standar, kami memiliki panggilan balik pesan ruangan.
client1 . OnTcpRoomMesssageReceived += ( roomName , message ) => ..
client1 . OnUdpRoomMesssageReceived += ( roomName , message ) => ..
client1 . OnTcpMessageReceived += ( message ) => ..
client1 . OnUdpMessageReceived += ( message ) => ..
Semua varian TCP aman menerapkan soket SSL standar dengan otentikasi/validasi TLS. Untuk info lebih lanjut, lihat: Keamanan