TCP Session¶
TcpSession is the core TCP client transport in Nalix.SDK. It handles the full lifecycle of a client connection, including reconnection logic, packet serialization, framed transport, and asynchronous message dispatching.
Client-side transport
TcpSession is a client-side transport. Do not use it in server listener code. Server TCP connections are owned by Nalix.Network listener/connection types and processed through Nalix.Runtime.
Lifecycle Flow¶
sequenceDiagram
participant A as Application
participant S as TcpSession
participant R as FrameReader
participant W as FrameSender
participant N as TCP Socket
A->>S: ConnectAsync(host, port, ct)
S->>S: acquire connection lock
S->>N: Socket.ConnectAsync()
S-->>A: OnConnected
S->>R: start ReceiveLoopAsync on LongRunning task
A->>S: SendAsync(packet, encrypt, ct)
S->>S: mark packet RELIABLE + serialize to BufferLease
S->>W: FrameSender.SendAsync(lease, encrypt, ct)
W->>N: transform, frame, lock, Socket.SendAsync
N-->>R: length-prefixed frame bytes
R->>R: validate length, reassemble, ProcessInbound
R->>S: HandleReceiveMessage(IBufferLease)
S-->>A: OnMessageReceived sync event
S-->>A: OnMessageAsync with retained lease
Source mapping¶
src/Nalix.SDK/Transport/TcpSession.cssrc/Nalix.SDK/Transport/Internal/FrameReader.cssrc/Nalix.SDK/Transport/Internal/FrameSender.cssrc/Nalix.Codec/Transforms/FramePipeline.cs
Role and Design¶
TcpSession acts as a high-level wrapper around a raw socket, providing a packet-oriented interface. It uses pooled BufferLease memory and the shared frame helpers to minimize GC pressure for high-throughput clients.
- Asynchronous Loop:
ConnectAsync(...)starts a long-running receive task throughFrameReader.ReceiveLoopAsync(...). - Unified Framing: Outbound and inbound payloads go through
FrameSender,FrameReader, andFramePipeline. - Error Handling: Centralized
OnErrorandOnDisconnectedevents for resilient client behavior. - Request Helpers:
RequestAsync<TResponse>()and the higher-level extension helpers handle subscribe-before-send request flows.
Public API¶
Events¶
| Member | Description |
|---|---|
OnConnected |
Raised when the socket connection is successfully established. |
OnDisconnected |
Raised when the connection is closed or lost. |
OnMessageReceived |
Synchronous event providing an IBufferLease for each frame. |
OnMessageAsync |
Async callback receiving ReadOnlyMemory<byte> after the transport retains the underlying lease. |
OnError |
Reports general transport or protocol errors. |
Methods¶
| Member | Description |
|---|---|
ConnectAsync(...) |
Establishes a connection to the primary or override destination. |
DisconnectAsync() |
Gracefully shuts down the connection. |
SendAsync(IPacket) |
Serializes and sends a packet with standard framing. |
SendAsync(payload) |
Sends raw binary data with required framing. |
RequestAsync<TResponse>(...) |
Sends a request and waits for a matching typed response. |
Dispose() |
Full resource cleanup and socket closure. |
Basic usage¶
var options = ConfigurationManager.Instance.Get<TransportOptions>();
var catalog = new PacketRegistryFactory()
.RegisterPacket<LoginPacket>()
.RegisterPacket<LoginResponse>()
.CreateCatalog();
using var client = new TcpSession(options, catalog);
client.OnConnected += (s, e) => Console.WriteLine("Connected!");
client.OnMessageReceived += (s, lease) =>
{
Console.WriteLine($"Received {lease.Length} bytes");
};
await client.ConnectAsync();
await client.HandshakeAsync();
await client.SendAsync(new LoginPacket { Username = "Ghost" });
var loginResponse = await client.RequestAsync<LoginResponse>(
new LoginPacket { Username = "Ghost" },
RequestOptions.Default.WithTimeout(5_000));
Notes¶
OnMessageReceivedprovides rawIBufferLeaseaccess. Do not dispose the original lease inside the handler unless you first calledRetain();src/Nalix.SDK/Transport/TcpSession.cskeeps ownership of the original callback lifetime.RequestAsync<TResponse>()subscribes before sending the packet, which avoids losing fast responses on low-latency servers.OnMessageAsyncis optional and receiveslease.Memory, not a packet object. Use it for custom async processing on the receive flow.