Server Boilerplate Template¶
Learning Signals
- Level: Beginner to Intermediate
- Time: 5 minutes (Copy-Paste)
- Prerequisites: Quickstart
This page provides a robust, production-ready starting point for any Nalix server. It is structured to be easy to copy into a new project while allowing for deep customization as your needs grow.
1. The Simplest Entry Point (Hosting Builder)¶
For 99% of applications, the Hosting Builder is the standard way to bootstrap. It handles dependency injection, service orchestration, and lifecycle management automatically.
using Microsoft.Extensions.Logging;
using Nalix.Logging;
using Nalix.Hosting;
using Nalix.Network.Options;
using Nalix.Environment.Configuration;
// 1. Load configuration from environment or .ini files
var socketOpts = ConfigurationManager.Instance.Get<NetworkSocketOptions>();
// 2. Build the application
using var app = NetworkApplication.CreateBuilder()
.ConfigureLogging(NLogix.Host.Instance)
.Configure<NetworkSocketOptions>(opt =>
{
opt.Port = socketOpts.Port;
opt.Backlog = 1024;
opt.EnableTimeout = true; // Enabled by default
})
.Configure<TimingWheelOptions>(opt =>
{
opt.IdleTimeoutMs = 60_000; // 60 second idle timeout
})
// 2.5. Configure Zero-Allocation Buffer Pooling
.ConfigureBufferPoolManager(new BufferPoolManager(NLogix.Host.Instance))
// Add your packet contracts
.ScanPackets<MyPingPacket>()
// Register your logic controllers
.AddHandler<MyPingHandler>()
// Attach the transport protocol
.BindTcp<MyProtocol>().Bind()
.Build();
// 3. Start the event loops
Console.WriteLine($"Server listening on port {socketOpts.Port}...");
await app.RunAsync();
2. Standard Application Components¶
In a real project, you should split these into separate files. This boilerplate shows them together for easy reference.
The Protocol (Network Bridge)¶
The protocol translates raw frames into clean objects. Keep this thin; its only job is to forward data to the dispatcher.
using Nalix.Abstractions.Networking;
using Nalix.Network.Protocols;
using Nalix.Runtime.Dispatching;
public sealed class MyProtocol : Protocol
{
private readonly IPacketDispatch _dispatch;
// The hosting builder automatically injects the IPacketDispatch instance
public MyProtocol(IPacketDispatch dispatch) => _dispatch = dispatch;
public override void ProcessMessage(object? sender, IConnectEventArgs args)
=> _dispatch.HandlePacket(args.Lease, args.Connection);
}
The Handler (Business Logic)¶
Handlers are where your application logic lives. Use IPacketContext<T> to access the packet and the connection safely.
using Nalix.Abstractions.Networking.Packets;
[PacketController("SystemHandlers")]
public sealed class MyPingHandler
{
[PacketOpcode(0x1001)]
public MyPongPacket OnPing(IPacketContext<MyPingPacket> context)
{
return new MyPongPacket { Message = "Pong!" };
}
}
3. Advanced Configuration (Middleware & Policy)¶
Add these to your CreateBuilder() chain to harden your server for production traffic.
builder.ConfigureDispatch(options =>
{
options.WithLogging(NLogix.Host.Instance)
// Add security layers
.WithMiddleware(new ConcurrencyMiddleware())
.WithMiddleware(new RateLimitMiddleware())
// Handle global failures
.WithErrorHandling((ex, opcode) =>
{
Console.WriteLine($"Error in opcode 0x{opcode:X4}: {ex.Message}");
});
});
4. Low-Level Manual Composition (Direct Path)¶
Advanced Only
Use this path only if you are building specialized transport libraries or need to bypass the Hosting layer for extreme performance tuning.
// Manual setup of all components without the Hosting builder.
// Prefer the Hosting Builder above unless you are writing transport-level code.
public sealed class ManualTcpListener : TcpListenerBase
{
public ManualTcpListener(ushort port, IProtocol protocol, IConnectionHub hub)
: base(port, protocol, hub) { }
}
PacketDispatchChannel dispatch = new(options =>
{
options.WithHandler(() => new MyPingHandler());
});
IConnectionHub hub = new ConnectionHub();
MyProtocol protocol = new(dispatch);
ManualTcpListener listener = new(5000, protocol, hub);
dispatch.Activate();
listener.Activate();
// ... run ...
listener.Deactivate();
hub.Dispose();
dispatch.Dispose();
Manual dependency wiring
TcpListenerBase is abstract and its current constructors require an
IConnectionHub. The Hosting builder creates the concrete internal listener
and hub automatically; manual composition must provide both explicitly.
Best Practices Checklist¶
- [x] Contracts: Keep packet POCOs in a separate project shared with the client.
- [x] Logging: Always use
NLogixor a production-readyILogger. - [x] Validation: Call
.Validate()on all Options objects before booting. - [x] Protocols: Use
ValidateConnection(...),IsAccepting, andSetConnectionAcceptance(bool)intentionally.src/Nalix.Network/Protocols/Protocol.Core.csandsrc/Nalix.Network/Protocols/Protocol.PublicMethods.csshow that the protocol exposes both the atomic property and the public helper method, whilesrc/Nalix.Hosting/DefaultProtocol.csalready enables acceptance for the common dispatch-forwarding path.