Skip to content

End-to-End Sample

This guide shows the smallest useful Nalix TCP server flow:

  1. register shared services
  2. build a packet dispatcher
  3. forward frames from Protocol into dispatch
  4. start a TcpListenerBase
  5. send one request and receive one response

The sample is intentionally small so clients can copy the structure first and optimize later.

Server

1. Register shared services

InstanceManager.Instance.Register<ILogger>(logger);
InstanceManager.Instance.Register<IPacketRegistry>(packetRegistry);

2. Create handlers

[PacketController("SamplePingHandlers")]
public sealed class SamplePingHandlers
{
    [PacketOpcode(0x1001)]
    public ValueTask<PingResponse> Ping(PingRequest request, IConnection connection)
    {
        PingResponse response = new()
        {
            Message = $"pong:{request.Message}"
        };

        return ValueTask.FromResult(response);
    }
}

3. Build the dispatcher

PacketDispatchChannel dispatch = new(options =>
{
    options.WithLogging(logger)
           .WithHandler(() => new SamplePingHandlers());
});

dispatch.Activate();

4. Bridge protocol to dispatch

public sealed class SampleProtocol : Protocol
{
    private readonly PacketDispatchChannel _dispatch;

    public SampleProtocol(PacketDispatchChannel dispatch) => _dispatch = dispatch;

    public override void ProcessMessage(object sender, IConnectEventArgs args)
        => _dispatch.HandlePacket(args.Lease, args.Connection);
}

5. Start the listener

public sealed class SampleTcpListener : TcpListenerBase
{
    public SampleTcpListener(ushort port, IProtocol protocol) : base(port, protocol) { }
}

SampleTcpListener listener = new(57206, new SampleProtocol(dispatch));
listener.Activate();

Client

The transport/session abstraction can vary on your side, but the request/response pattern is:

PingRequest request = new()
{
    Message = "hello"
};

await client.SendAsync(request.Serialize());
PingResponse response = await WaitForPingResponseAsync();

Console.WriteLine(response.Message); // pong:hello

Full flow

sequenceDiagram
    participant Client
    participant Listener as TcpListenerBase
    participant Protocol as SampleProtocol
    participant Dispatch as PacketDispatchChannel
    participant Handler as SamplePingHandlers

    Client->>Listener: TCP frame
    Listener->>Protocol: connection message event
    Protocol->>Dispatch: HandlePacket(lease, connection)
    Dispatch->>Handler: Ping(request, connection)
    Handler-->>Dispatch: PingResponse
    Dispatch-->>Client: serialized response

What to customize next

  • add middleware
  • add packet attributes such as timeout, permission, or rate limit
  • switch some handlers to PacketContext<TPacket> when you need explicit manual sending