A minimal, beginner-friendly client/server sample built with Nalix.
- Defining request/response packets with
[Packet]and[PacketOpcode] - Writing a server packet handler with
[PacketHandler] - Bootstrapping a TCP server using
NetworkApplication.CreateBuilder() - Connecting a client with
TcpSessionand callingRequestAsync<TResponse>() - Graceful shutdown with
CancellationToken
HelloWorld/
├── HelloWorld.Contracts/ # Shared packet definitions
│ ├── HelloWorld.Contracts.csproj
│ ├── HelloRequestPacket.cs
│ └── HelloResponsePacket.cs
│
├── HelloWorld.Server/ # Server application
│ ├── HelloWorld.Server.csproj
│ ├── Program.cs
│ └── HelloHandlers.cs
│
├── HelloWorld.Client/ # Client application
│ ├── HelloWorld.Client.csproj
│ └── Program.cs
│
├── HelloWorld.sln # Solution file
└── README.md
From the repository root:
dotnet build samples/HelloWorld/HelloWorld.slnOpen two terminals.
dotnet run --project samples/HelloWorld/HelloWorld.ServerYou should see:
HelloWorld server is running on 127.0.0.1:57206.
Press Ctrl+C to stop.
dotnet run --project samples/HelloWorld/HelloWorld.ClientYou should see:
Connected to 127.0.0.1:57206.
Server replied: Hello from Nalix!
Press Ctrl+C in Terminal 1 to stop the server.
Defines the two packets shared between client and server:
| Packet | Opcode | Direction | Purpose |
|---|---|---|---|
HelloRequestPacket |
0x7001 |
Client → Server | Sends a greeting |
HelloResponsePacket |
0x7002 |
Server → Client | Returns a reply |
Both extend PacketBase<T>, which provides automatic serialization, pooling,
and header management. The [Packet] attribute enables source-generated
packet registry entries, and [GenerateFormatter] produces a high-performance
binary serializer at compile time.
Bootstraps the server using the canonical Hosting API:
NetworkApplication.CreateBuilder()
.UseLogger(logger)
.MapHandlers(typeof(HelloHandlers))
.ListenTcp<DefaultProtocol>().OnPort(57206).Bind()
.Build();HelloHandlers is a static class marked with [PacketHandler].
Its HandleHelloAsync method is routed by [PacketOpcode(0x7001)].
Uses Nalix.SDK.Transport.TcpSession to connect and exchange packets:
using TcpSession session = new(options);
await session.ConnectAsync("127.0.0.1", 57206);
HelloResponsePacket response = await session.RequestAsync<HelloResponsePacket>(
new HelloRequestPacket(),
RequestOptions.Default.WithTimeout(5_000));RequestAsync<TResponse> handles subscribe → send → await → timeout
→ unsubscribe internally, so no response is ever missed.
Client Server
│ │
│ HelloRequestPacket (0x7001) │
│ ─────────────────────────────► │
│ │ PacketDispatchChannel
│ │ routes to HelloHandlers.HandleHelloAsync
│ │
│ HelloResponsePacket (0x7002) │
│ ◄───────────────────────────── │
│ │
Another process is listening on port 57206. Stop it, or change the port
constant in Program.cs (server) and the TransportOptions (client).
Make sure the server is running before you start the client.
Verify that 127.0.0.1:57206 is reachable (no firewall blocking it).
Ensure the HelloWorld.Contracts assembly is loaded.
The source-generated ModuleInitializer registers packets automatically
when the assembly loads. If you removed the [Packet] attribute or changed
the base class, re-add it and rebuild.
This sample uses project references to the Nalix source tree.
Make sure you cloned the full repository and that the paths in the .csproj
files resolve correctly relative to the sample folder.