Sessions & Lifetimes
NexNet creates a new hub instance for each client session. Understanding the lifecycle helps you manage state correctly and use features like session groups for targeted broadcasting.
Hub Instance Lifecycle
A new nexus instance is created for each client that connects. The instance remains active for the duration of the session and is automatically disposed when the session ends — whether from client disconnection, error, or timeout.
Because nexus instances may be created and disposed temporarily (for example, by NexusServer<>.ContextProvider), avoid performing calculations or side effects in constructors.
Each session gets its own nexus instance. Data is not shared between sessions through the nexus class itself. For shared state, use external services or synchronized collections.
Session Groups
Sessions can be added to named groups for targeted broadcasting. Group membership is managed through the Context.Groups API within server nexus methods:
[Nexus<IServerNexus, IClientNexus>(NexusType = NexusType.Server)]
partial class ServerNexus
{
public async ValueTask JoinRoom(string roomId)
{
// Add this session to a group
await Context.Groups.AddAsync($"room-{roomId}");
}
public async ValueTask Setup()
{
// Add to multiple groups at once
await Context.Groups.AddAsync(["lobby", "players"]);
// Remove from a group
await Context.Groups.RemoveAsync("lobby");
// Get all group names for this session
var groups = await Context.Groups.GetNamesAsync();
}
}
Broadcasting to Groups
// Send to all members of a group
await Context.Clients.Group("room-123").SendMessage("Hello room!");
// Send to members of multiple groups
await Context.Clients.Groups(["lobby", "players"]).SendMessage("Hello all!");
Groups are automatically cleaned up when sessions disconnect. You don't need to manually remove sessions from groups on disconnection.
Ping and Keep-Alive
NexNet includes a built-in ping system to detect connection timeouts from both the client and server side. Ping messages are sent periodically (ClientConfig.PingInterval, 10 seconds by default), and if nothing is received within ConfigBase.Timeout (30 seconds by default), the connection is considered lost.
Timeouts
| Setting | Default | Disconnects when |
|---|---|---|
Timeout |
30 s | Nothing is received from the peer, including pings. |
HandshakeTimeout |
15 s | The connection is not established and authenticated in time. |
ProgressTimeout |
30 s | An operation that holds session memory stops making progress: a large argument or result being received, a channel item larger than its pipe's window, a pipe close the peer does not confirm, or a send to the transport that does not complete. The reason is DisconnectReason.Stalled. |
Waiting for a slow reader is not a stall: a pipe writer waits for credit as long as the reader takes. See Limits and Flow Control.
Automatic Reconnection
Clients reconnect automatically when ClientConfig.ReconnectionPolicy is set. It is null by default, which disables reconnection.
// Retries at 0 s, 2 s, 10 s and 30 s, then every 30 s.
clientConfig.ReconnectionPolicy = new DefaultReconnectionPolicy();
The policy decides which disconnect reasons are reconnected for. By default these are DisconnectReason.SocketError, DisconnectReason.Timeout and DisconnectReason.ServerRestarting; any other reason leaves the client disconnected. A server that restarts by stopping (for example, a daemon restarted by its service manager) disconnects its clients with DisconnectReason.ServerShutdown. To reconnect to it, add that reason:
clientConfig.ReconnectionPolicy = new DefaultReconnectionPolicy
{
ReconnectReasons = new HashSet<DisconnectReason>
{
DisconnectReason.SocketError,
DisconnectReason.Timeout,
DisconnectReason.ServerRestarting,
DisconnectReason.ServerShutdown
}
};
DisconnectReason.Graceful (which includes the client's own DisconnectAsync) and DisconnectReason.Authentication are best left out. A custom IReconnectionPolicy can override ShouldReconnect(DisconnectReason) to decide; if it does not, it reconnects for the default reasons.
During reconnection:
- The client detects the connection loss
- A new connection is established to the server
- A new session and nexus instance are created on the server side
- The client can resume invoking methods on the proxy
See Also
- Hub Invocations — Method patterns and broadcasting
- Synchronized Collections — Data sync across sessions
- Authentication — Securing session connections
- Limits and Flow Control — Session memory, pipe windows and timeouts