Skip to content

aizuon/nexum

Repository files navigation

Nexum

A high-performance networking library for .NET 10 designed for real-time multiplayer games. The name "Nexum" comes from Latin, meaning "bond" or "connection" β€” reflecting the library's purpose of creating reliable network connections. Features TCP and UDP communication with NAT hole punching, reliable UDP, server-orchestrated P2P groups with direct and relayed messaging, AES/RC4 encryption, and zero-allocation optimizations.

Note: This library was inspired by ProudNet, a commercial networking solution.

.NET License

✨ Features

Server-Client Communication

  • TCP (Default) - Reliable, ordered message delivery using DotNetty
  • UDP via NAT Hole Punching - Optional low-latency UDP channel established through automatic NAT traversal
    • Unreliable UDP - Fire-and-forget for real-time data (position updates, etc.)
    • Reliable UDP - Guaranteed delivery over UDP with automatic retransmission and ordering
  • MTU Discovery - Binary search algorithm discovers optimal MTU by piggybacking probes on ping/pong packets
  • Auto Fragmentation - Large UDP packets automatically fragmented and reassembled with adaptive MTU
  • Message Compression - Zlib compression for bandwidth optimization
  • Server Time Sync - Client can synchronize with server time

Peer-to-Peer (P2P)

  • P2P Groups - Server orchestrates client-to-client UDP connections
  • P2P NAT Hole Punching - Direct peer-to-peer connections through NAT
  • Direct P2P - Send messages directly between peers over UDP
  • P2P MTU Discovery - Each peer pair discovers optimal MTU independently
  • Relayed P2P - Fallback relay through server when direct connection fails
    • TCP Relay - Relayed messages through server TCP
    • UDP Relay - Relayed messages through server UDP (supports both reliable and unreliable)

Security

  • RSA Key Exchange - Secure 2048-bit RSA key exchange during connection
  • AES Encryption - Secure message encryption (configurable key length, default 256-bit)
  • RC4 Fast Encryption - High-performance encryption for real-time data (configurable key length, default 512-bit)
  • Per-Session Keys - Unique encryption keys generated for each client session

Performance

  • Asynchronous I/O - Built on DotNetty for high-performance async networking
  • UDP Socket Pool - Multiple UDP listener sockets with random assignment for load distribution
  • Efficient Serialization - Custom binary serialization with NetMessage
  • Zero-Allocation Patterns - GC.AllocateUninitializedArray, ArrayPool<T>, stackalloc for small buffers, Span<T>, and BinaryPrimitives
  • Optimized Thread Pools - DotNetty MultithreadEventLoopGroup auto-scales to CPU core count
  • Adaptive Fragmentation - MTU inferred from incoming fragments for efficient reassembly

Packet Serialization (Source Generator)

  • Compile-Time Code Generation - Roslyn source generator automatically creates serialization and deserialization methods
  • Attribute-Based - Simple attributes define packet structure and property order
  • Type-Safe - Strong typing for packet properties with automatic serialization order
  • Custom Serializers - Support for custom serializers for complex or non-standard types
  • Zero Boilerplate - No manual serialization code needed for marked packets

πŸ“¦ Project Structure

Nexum/
β”œβ”€β”€ BaseLib/                        # Core utilities and extensions
β”‚   β”œβ”€β”€ Caching/
β”‚   β”‚   └── MemoryCache.cs
β”‚   β”œβ”€β”€ Extensions/
β”‚   β”‚   β”œβ”€β”€ ByteArrayExtensions.cs
β”‚   β”‚   β”œβ”€β”€ ConcurrentDictionaryExtensions.cs
β”‚   β”‚   β”œβ”€β”€ DateTimeExtensions.cs
β”‚   β”‚   β”œβ”€β”€ DictionaryExtensions.cs
β”‚   β”‚   β”œβ”€β”€ ExceptionExtensions.cs
β”‚   β”‚   β”œβ”€β”€ IPEndPointExtensions.cs
β”‚   β”‚   β”œβ”€β”€ SemaphoreSlimExtensions.cs
β”‚   β”‚   β”œβ”€β”€ StreamExtensions.cs
β”‚   β”‚   └── SymmetricAlgorithmExtensions.cs
β”‚   β”œβ”€β”€ Hashing/
β”‚   β”‚   β”œβ”€β”€ CRC32.cs
β”‚   β”‚   └── Hash.cs
β”‚   β”œβ”€β”€ IO/
β”‚   β”‚   └── NonClosingStream.cs
β”‚   β”œβ”€β”€ Logging/
β”‚   β”‚   └── ContextEnricher.cs
β”‚   β”œβ”€β”€ Patterns/
β”‚   β”‚   └── Singleton.cs
β”‚   β”œβ”€β”€ Threading/
β”‚   β”‚   β”œβ”€β”€ TaskLoop.cs
β”‚   β”‚   └── ThreadLoop.cs
β”‚   └── Events.cs
β”œβ”€β”€ Nexum.SourceGen/                # Roslyn source generator for packet serialization
β”‚   └── NetSerializableGenerator.cs
β”œβ”€β”€ Nexum.Core/                     # Shared networking core
β”‚   β”œβ”€β”€ Logging/
β”‚   β”‚   β”œβ”€β”€ BurstDuplicateLogFilter.cs
β”‚   β”‚   └── BurstDuplicateLogger.cs
β”‚   └── Nexum/
β”‚       β”œβ”€β”€ Attributes/             # Source generator attributes
β”‚       β”‚   β”œβ”€β”€ INetPropertySerializer.cs
β”‚       β”‚   β”œβ”€β”€ NetCoreMessageAttribute.cs
β”‚       β”‚   β”œβ”€β”€ NetPropertyAttribute.cs
β”‚       β”‚   β”œβ”€β”€ NetSerializableAttribute.cs
β”‚       β”‚   β”œβ”€β”€ ScalarSerializer.cs
β”‚       β”‚   β”œβ”€β”€ StringEndPointSerializer.cs
β”‚       β”‚   └── UnicodeStringSerializer.cs
β”‚       β”œβ”€β”€ Configuration/          # Settings and configuration
β”‚       β”‚   β”œβ”€β”€ Constants.cs
β”‚       β”‚   β”œβ”€β”€ Enums.cs
β”‚       β”‚   β”œβ”€β”€ FragmentConfig.cs
β”‚       β”‚   β”œβ”€β”€ HolepunchConfig.cs
β”‚       β”‚   β”œβ”€β”€ MtuConfig.cs
β”‚       β”‚   β”œβ”€β”€ NetConfig.cs
β”‚       β”‚   β”œβ”€β”€ NetSettings.cs
β”‚       β”‚   └── ReliableUdpConfig.cs
β”‚       β”œβ”€β”€ Crypto/                 # Encryption and compression
β”‚       β”‚   β”œβ”€β”€ NetCrypt.cs
β”‚       β”‚   β”œβ”€β”€ NetZip.cs
β”‚       β”‚   └── RSAHelper.cs
β”‚       β”œβ”€β”€ DotNetty/Codecs/        # DotNetty codec implementations
β”‚       β”‚   β”œβ”€β”€ LengthFieldBasedFrameDecoder.cs
β”‚       β”‚   β”œβ”€β”€ NexumFrameDecoder.cs
β”‚       β”‚   β”œβ”€β”€ NexumFrameEncoder.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpCodecHandler.cs
β”‚       β”‚   β”œβ”€β”€ UdpDefragmentationDecoder.cs
β”‚       β”‚   β”œβ”€β”€ UdpFrameDecoder.cs
β”‚       β”‚   β”œβ”€β”€ UdpFragmentationEncoder.cs
β”‚       β”‚   └── UdpFrameEncoder.cs
β”‚       β”œβ”€β”€ Events/                 # Event arguments
β”‚       β”‚   β”œβ”€β”€ ConnectionStateChangedEventArgs.cs
β”‚       β”‚   └── SessionConnectionStateChangedEventArgs.cs
β”‚       β”œβ”€β”€ Fragmentation/          # UDP packet fragmentation types
β”‚       β”‚   β”œβ”€β”€ AssembledPacket.cs
β”‚       β”‚   β”œβ”€β”€ AssembledPacketError.cs
β”‚       β”‚   └── DefraggingPacket.cs
β”‚       β”œβ”€β”€ Holepunching/           # NAT hole punching
β”‚       β”‚   └── HolepunchHelper.cs
β”‚       β”œβ”€β”€ Message/                # Core message packets
β”‚       β”œβ”€β”€ Mtu/                    # MTU discovery
β”‚       β”‚   └── MtuDiscovery.cs
β”‚       β”œβ”€β”€ ReliableUdp/            # Reliable UDP implementation
β”‚       β”‚   β”œβ”€β”€ CompressedFrameNumbers.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpFrame.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpHelper.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpHost.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpReceiver.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpSender.cs
β”‚       β”‚   └── StreamQueue.cs
β”‚       β”œβ”€β”€ Rmi/                    # RMI packets (S2C, C2S, C2C)
β”‚       β”œβ”€β”€ Routing/                # Host identification
β”‚       β”‚   β”œβ”€β”€ FilterTag.cs
β”‚       β”‚   └── HostId.cs
β”‚       β”œβ”€β”€ Serialization/          # Binary serialization
β”‚       β”‚   β”œβ”€β”€ ByteArray.cs
β”‚       β”‚   └── NetMessage.cs
β”‚       β”œβ”€β”€ Simulation/             # Network simulation for testing
β”‚       β”‚   β”œβ”€β”€ NetworkProfile.cs
β”‚       β”‚   β”œβ”€β”€ NetworkSimulation.cs
β”‚       β”‚   └── SimulatedUdpChannelHandler.cs
β”‚       β”œβ”€β”€ Udp/                    # UDP message types
β”‚       β”‚   β”œβ”€β”€ OutboundUdpPacket.cs
β”‚       β”‚   β”œβ”€β”€ ReliableUdpMessages.cs
β”‚       β”‚   └── UdpMessage.cs
β”‚       β”œβ”€β”€ Utilities/              # Helper utilities
β”‚       β”‚   β”œβ”€β”€ EventLoopScheduler.cs
β”‚       β”‚   β”œβ”€β”€ Extensions.cs
β”‚       β”‚   β”œβ”€β”€ NetUtil.cs
β”‚       β”‚   └── SysUtil.cs
β”‚       β”œβ”€β”€ ITimeSource.cs
β”‚       β”œβ”€β”€ ModuleInit.cs
β”‚       β”œβ”€β”€ NetCore.cs
β”‚       └── NetCoreHandler.cs
β”œβ”€β”€ Nexum.Client/                   # Client-side implementation
β”‚   └── Nexum/
β”‚       β”œβ”€β”€ Core/                   # Client core
β”‚       β”‚   β”œβ”€β”€ NetClient.cs
β”‚       β”‚   β”œβ”€β”€ NetClientAdapter.cs
β”‚       β”‚   └── NetClientHandler.cs
β”‚       β”œβ”€β”€ P2P/                    # P2P client components
β”‚       β”‚   β”œβ”€β”€ P2PGroup.cs
β”‚       β”‚   └── P2PMember.cs
β”‚       β”œβ”€β”€ Udp/                    # UDP handling
β”‚       β”‚   β”œβ”€β”€ RecycledUdpSocket.cs
β”‚       β”‚   └── UdpHandler.cs
β”‚       └── Utilities/              # Client-specific utilities
β”‚           β”œβ”€β”€ NetUtil.cs
β”‚           └── SysUtil.cs
β”œβ”€β”€ Nexum.Server/                   # Server-side implementation
β”‚   └── Nexum/
β”‚       β”œβ”€β”€ Core/                   # Server core
β”‚       β”‚   β”œβ”€β”€ ChannelAttributes.cs
β”‚       β”‚   β”œβ”€β”€ HostIdFactory.cs
β”‚       β”‚   β”œβ”€β”€ NetServer.cs
β”‚       β”‚   β”œβ”€β”€ NetServerAdapter.cs
β”‚       β”‚   └── NetServerHandler.cs
β”‚       β”œβ”€β”€ P2P/                    # P2P server components
β”‚       β”‚   β”œβ”€β”€ P2PConnectionState.cs
β”‚       β”‚   β”œβ”€β”€ P2PGroup.cs
β”‚       β”‚   └── P2PMember.cs
β”‚       β”œβ”€β”€ Sessions/               # Session management
β”‚       β”‚   β”œβ”€β”€ NetSession.cs
β”‚       β”‚   └── SessionHandler.cs
β”‚       └── Udp/                    # UDP handling
β”‚           β”œβ”€β”€ UdpHandler.cs
β”‚           └── UdpSocket.cs
β”œβ”€β”€ Nexum.Tests/                    # Unit and integration tests
β”‚   β”œβ”€β”€ Integration/
β”‚   β”‚   β”œβ”€β”€ ConnectionStateTests.cs
β”‚   β”‚   β”œβ”€β”€ ConnectionTests.cs
β”‚   β”‚   β”œβ”€β”€ EdgeCaseTests.cs
β”‚   β”‚   β”œβ”€β”€ IntegrationTestBase.cs
β”‚   β”‚   β”œβ”€β”€ IntegrationTestCollection.cs
β”‚   β”‚   β”œβ”€β”€ KeyExchangeTests.cs
β”‚   β”‚   β”œβ”€β”€ MtuDiscoveryTests.cs
β”‚   β”‚   β”œβ”€β”€ P2PConnectionTests.cs
β”‚   β”‚   β”œβ”€β”€ ReliableUdpTests.cs
β”‚   β”‚   β”œβ”€β”€ StressTests.cs
β”‚   β”‚   β”œβ”€β”€ UdpConnectionTests.cs
β”‚   β”‚   β”œβ”€β”€ UdpFragmentationTests.cs
β”‚   β”‚   └── UdpReconnectionTests.cs
β”‚   β”œβ”€β”€ ByteArrayTests.cs
β”‚   β”œβ”€β”€ CRC32Tests.cs
β”‚   β”œβ”€β”€ NetCryptTests.cs
β”‚   β”œβ”€β”€ NetMessageTests.cs
β”‚   β”œβ”€β”€ NetPacketSourceGenTests.cs
β”‚   └── NetZipTests.cs
β”œβ”€β”€ Nexum.Tests.E2E/                # End-to-end AWS tests
β”‚   β”œβ”€β”€ Orchestration/
β”‚   β”‚   β”œβ”€β”€ Ec2Orchestrator.cs
β”‚   β”‚   β”œβ”€β”€ IamProvisioner.cs
β”‚   β”‚   β”œβ”€β”€ S3Deployer.cs
β”‚   β”‚   └── SsmCommandRunner.cs
β”‚   β”œβ”€β”€ AwsConfig.cs
β”‚   └── CoreFeaturesE2ETest.cs
β”œβ”€β”€ Nexum.E2E.Client/               # E2E test client application
β”‚   └── Program.cs
β”œβ”€β”€ Nexum.E2E.Server/               # E2E test server application
β”‚   └── Program.cs
β”œβ”€β”€ Nexum.E2E.Common/               # Shared E2E constants
β”‚   └── E2EConstants.cs
β”œβ”€β”€ Example.Client/                 # Example client application
β”‚   └── Program.cs
└── Example.Server/                 # Example server application
    └── Program.cs

πŸš€ Quick Start

Prerequisites

  • .NET 10.0 SDK or later
  • Visual Studio 2022+ or VS Code with C# extension

Installation

Clone the repository and build the solution:

git clone https://github.com/aizuon/nexum.git
cd nexum
dotnet build Nexum.sln

Server Example

using System.Net;
using Nexum.Core;
using Nexum.Server;

const string serverName = "Relay";
var serverGuid = new Guid("a43a97d1-9ec7-495e-ad5f-8fe45fde1151");

// Create a server instance
var server = new NetServer(serverName, serverGuid);

// Handle incoming RMI messages
server.OnRmiReceive += (session, message, rmiId) =>
{
    switch (rmiId)
    {
        case 1: // Custom message handler
            // Read message data
            message.Read(out int value);
            
            // Send response back to client
            var response = new NetMessage();
            response.Write(value * 2);
            session.RmiToClient(2, response);
            break;
    }
};

// Start listening with TCP and UDP ports
await server.ListenAsync(
    new IPEndPoint(IPAddress.Any, 28000),      // TCP endpoint
    new uint[] { 29000, 29001, 29002, 29003 }  // UDP ports
);

Client Example

using System.Net;
using Nexum.Core;
using Nexum.Client;

const string serverName = "Relay";
var serverGuid = new Guid("a43a97d1-9ec7-495e-ad5f-8fe45fde1151");

// Create a client instance
var client = new NetClient(serverName, serverGuid);

// Handle connection completion
client.OnConnectionComplete += () =>
{
    Console.WriteLine($"Connected with HostId: {client.HostId}");
    
    // Send a message to the server
    var message = new NetMessage();
    message.Write(42);
    client.RmiToServer(1, message);
};

// Handle incoming RMI messages
client.OnRmiReceive += (message, rmiId) =>
{
    message.Read(out int result);
    Console.WriteLine($"Received response: {result}");
};

// Connect to server
await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 28000));

πŸ”§ Configuration

Server Settings

Configure the server behavior using NetSettings:

var settings = new NetSettings
{
    // Transport settings
    EnableNagleAlgorithm = true,          // TCP Nagle algorithm
    IdleTimeout = 900,                    // Session idle timeout (seconds)

    // Message settings
    MessageMaxLength = 1048576,           // Max message size (1MB)
    
    // Security settings
    EncryptedMessageKeyLength = 256,      // AES key length (bits)
    FastEncryptedMessageKeyLength = 512,  // RC4 key length (bits)
    
    // P2P settings
    EnableP2PEncryptedMessaging = false,  // Encryption for P2P messages
    DirectP2PStartCondition = DirectP2PStartCondition.Always, // When to initiate direct P2P holepunching
};

var server = new NetServer("Relay", new Guid("a43a97d1-9ec7-495e-ad5f-8fe45fde1151"), settings);

πŸ“‘ P2P Communication

Creating P2P Groups

// Server-side: Create a P2P group and add clients
var group = server.CreateP2PGroup();

// Add clients to the group
group.Join(session1);
group.Join(session2);

// Remove clients from the group
group.Leave(session1);

P2P Messaging (Client-side)

// After joining a P2P group, access peers
var peer = client.P2PGroup.P2PMembers[targetHostId];

// Send message to peer (via relay if direct connection not established)
var message = new NetMessage();
message.Write("Hello, peer!");
peer.RmiToPeer(7001, message, reliable: true, relay: true);

// Send directly (requires established direct connection)
peer.RmiToPeer(7001, message, reliable: false, relay: false);

πŸ“¨ Message Serialization

NetMessage provides comprehensive serialization support:

var message = new NetMessage();

// Write primitive types
message.Write(42);                    // int
message.Write(3.14f);                 // float
message.Write(true);                  // bool
message.Write("Hello");               // string (Latin1)
message.Write("Hello", unicode: true);// string (Unicode)

// Write complex types
message.Write(Guid.NewGuid());        // Guid
message.Write(new Version(1, 2, 3, 4)); // Version
message.Write(new IPEndPoint(IPAddress.Loopback, 8080)); // IPEndPoint
message.Write(new ByteArray(data));   // ByteArray
message.Write(MyEnum.Value);          // Enums

// Read data
message.Read(out int value);
message.Read(out string text);
message.Read(out Guid guid);
message.Read(out MyEnum enumValue);

Data Transfer Objects (DTOs)

Use [NetSerializable] to define DTOs with automatic serialization. The source generator creates Serialize() and Deserialize() methods at compile time:

using Nexum.Core.Attributes;

[NetSerializable]
public partial class PositionDto
{
    [NetProperty(0)]
    public float X { get; set; }

    [NetProperty(1)]
    public float Y { get; set; }

    [NetProperty(2)]
    public float Z { get; set; }
}

// Serialize
var dto = new PositionDto { X = 10.5f, Y = 0f, Z = -5.2f };
var message = dto.Serialize();

// Deserialize
if (PositionDto.Deserialize(message, out var received))
{
    Console.WriteLine($"Position at ({received.X}, {received.Y}, {received.Z})");
}

RMI Packets with Source Generator

Use [NetRmi] to define RMI packets with automatic ID assignment. The generated Serialize() method wraps the packet in an RmiMessage with the specified RMI ID:

// Define an enum for your RMI IDs (must use ushort as underlying type)
public enum GameRmiId : ushort
{
    PlayerMove = 1001,
    PlayerAttack = 1002,
    ChatMessage = 1003
}

[NetRmi(GameRmiId.PlayerMove)]
public partial class PlayerMoveRmi
{
    [NetProperty(0)]
    public uint PlayerId { get; set; }

    [NetProperty(1)]
    public PositionDto Position { get; set; }
}

// Server-side: Send RMI to client
var rmi = new PlayerMoveRmi 
{ 
    PlayerId = 1, 
    Position = new PositionDto { X = 10.5f, Y = 20.3f, Z = 0f }
};
session.RmiToClient(rmi);                           // TCP
session.RmiToClientUdpIfAvailable(rmi);             // UDP if available

// Client-side: Handle incoming RMI
client.OnRmiReceive += (message, rmiId) =>
{
    if (rmiId == (ushort)GameRmiId.PlayerMove &&
        PlayerMoveRmi.Deserialize(message, out var move))
    {
        Console.WriteLine($"Player {move.PlayerId} moved to ({move.Position.X}, {move.Position.Y}, {move.Position.Z})");
    }
};

You can also use raw ushort values for RMI IDs:

[NetRmi(1001)]
public partial class PlayerMoveRmi { /* ... */ }

Custom Serializers

Custom serializers can be specified for complex types:

[NetSerializable]
public partial class ServerInfo
{
    [NetProperty(0, typeof(StringEndPointSerializer))]
    public IPEndPoint Endpoint { get; set; }

    [NetProperty(1, typeof(UnicodeStringSerializer))]
    public string ServerName { get; set; }
}

Implement custom serializers by implementing INetPropertySerializer<T>:

public sealed class UnixTimestampSerializer : INetPropertySerializer<DateTime>
{
    public static void Serialize(NetMessage msg, DateTime obj)
    {
        long unixTime = new DateTimeOffset(obj).ToUnixTimeMilliseconds();
        msg.Write(unixTime);
    }

    public static bool Deserialize(NetMessage msg, out DateTime obj)
    {
        if (!msg.Read(out long unixTime))
        {
            obj = default;
            return false;
        }
        obj = DateTimeOffset.FromUnixTimeMilliseconds(unixTime).UtcDateTime;
        return true;
    }
}

πŸ” Security Architecture

Connection Handshake

  1. Client connects via TCP
  2. Server sends RSA public key (2048-bit)
  3. Client generates AES and RC4 session keys
  4. Client encrypts keys with server's RSA public key
  5. Encrypted keys sent to server
  6. Server decrypts and stores session keys
  7. All subsequent communication uses session keys

Encryption Modes

Mode Algorithm Use Case
Secure AES Sensitive data, authentication
Fast RC4 Real-time game data, position updates
None - Non-sensitive data

πŸ§ͺ Testing

Run the test suite:

# Run unit tests
dotnet test Nexum.Tests/Nexum.Tests.csproj --filter "FullyQualifiedName!~Integration"

# Run integration tests
dotnet test Nexum.Tests/Nexum.Tests.csproj --filter "FullyQualifiedName~Integration"

# Run all tests with coverage
dotnet test Nexum.Tests/Nexum.Tests.csproj --collect:"XPlat Code Coverage"

πŸ“Š Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         NetServer                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ TCP Channel β”‚  β”‚ UDP Sockets β”‚  β”‚     P2P Groups          β”‚  β”‚
β”‚  β”‚  (DotNetty) β”‚  β”‚   (Pool)    β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”       β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚Grp 1β”‚  β”‚Grp 2β”‚  ...  β”‚  β”‚
β”‚         β”‚                β”‚         β”‚  β””β”€β”€β”¬β”€β”€β”˜  β””β”€β”€β”¬β”€β”€β”˜       β”‚  β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                  β”‚                       β”‚        β”‚             β”‚
β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚        β”‚             β”‚
β”‚         β”‚   NetSession    β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚             β”‚
β”‚         β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚                       β”‚             β”‚
β”‚         β”‚  β”‚ NetCrypt  β”‚  β”‚                       β”‚             β”‚
β”‚         β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                       β”‚             β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚                                β”‚
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚    NetClient      β”‚             β”‚    NetClient    β”‚
         β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  │◄───────────►│ (P2P Direct or  β”‚
         β”‚  β”‚  P2PGroup   β”‚  β”‚    Direct   β”‚  Relay via      β”‚
         β”‚  β”‚  P2PMember  β”‚  β”‚    P2P      β”‚  Server)        β”‚
         β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”§ Dependencies

Package Version Purpose
DotNetty.Transport 0.7.6 Async networking framework
DotNetty.Codecs 0.7.6 Frame encoding/decoding
BouncyCastle.Cryptography 2.6.2 AES/RC4 encryption
Serilog 4.3.0 Structured logging

πŸ†” Server Identity (ServerName + ServerGuid)

Clients and servers identify the target server using:

  • ServerName (string): used for logging/context
  • ServerGuid (Guid): used to validate the handshake target

The client sends ServerGuid during the connection handshake, and the server validates it before accepting the connection.

πŸ“‹ TODO / Work In Progress

The following features are planned or partially implemented:

  • Advanced UDP Congestion Control - Enhance ReliableUdpHandler with TCP-friendly rate control (TFRC) or BBR-style algorithms to prevent packet loss under load
  • Super Peer / Host Selection - Automatically elect the best peer (lowest latency, best connectivity) as host in P2P groups for authoritative state sync
  • WiFi/Network Handover - Seamless reconnection when the client's network changes (e.g., WiFiβ†’mobile), preserving session state and recovering in-flight messages

βš™οΈ Configuration

Configurable Settings

Setting Type Default Description
NetSettings.EnableNagleAlgorithm bool true TCP Nagle algorithm
NetSettings.IdleTimeout double 900 Session idle timeout in seconds
NetSettings.MessageMaxLength uint 1048576 Maximum message size
NetSettings.EncryptedMessageKeyLength uint 256 AES key length in bits
NetSettings.FastEncryptedMessageKeyLength uint 512 RC4 key length in bits
NetSettings.EnableP2PEncryptedMessaging bool false Encryption for P2P messages
NetSettings.DirectP2PStartCondition DirectP2PStartCondition Always When to initiate direct P2P holepunching

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

About

High-performance .NET networking library for multiplayer games with TCP/UDP, NAT hole punching, P2P messaging, and encryption.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors