Idle Connection Timeout¶
Nalix provides a built-in mechanism to automatically detect and disconnect client connections that have been inactive for a specified duration. This is critical for reclaiming resources and protecting against persistent connection exhaustion (Slowloris-style attacks).
Learning Signals
- Level: Intermediate
- Time: 10 minutes
- Prerequisites: Minimal Server
1. The Timing Wheel Mechanism¶
Instead of using a separate Timer for every connection (which is expensive and causes GC pressure), Nalix uses a Hashed Timing Wheel.
How it Works¶
- Connections are placed into "buckets" on a virtual wheel.
- A single background worker "ticks" through these buckets at a fixed interval.
- Only connections in the current bucket are checked for idleness.
This ensures that even with 100,000+ concurrent connections, the CPU overhead remains constant and minimal.
graph TD
subgraph Wheel[Timing Wheel]
B1[Bucket 1]
B2[Bucket 2]
B3[Current Bucket]
B4[Bucket 4]
end
Loop[Background Worker] -->|Tick| B3
B3 -->|Check| C1[Connection A]
B3 -->|Check| C2[Connection B]
C1 -->|Idle > Limit| Disc[Disconnect]
C2 -->|Still Active| Resch[Reschedule to future bucket]
2. Configuration¶
Idle timeout is managed via NetworkSocketOptions (to enable/disable) and TimingWheelOptions (to tune the timing).
Method 1: Configuration Files (INI)¶
The framework's internal Bootstrap automatically loads these settings from .ini files in your executable directory.
network.ini
timing.ini
; The duration in milliseconds before an idle connection is closed
IdleTimeoutMs = 60000
; The precision of the idle check (lower = more precise but higher CPU)
TickDuration = 1000
; Number of buckets in the wheel (higher = fewer collisions)
BucketCount = 512
3. Method 2: Fluent Builder (C#)¶
If you prefer to configure the server in code, use the Configure<T> methods on the NetworkApplicationBuilder.
using Nalix.Hosting;
using Nalix.Network.Options;
var host = NetworkApplication.CreateBuilder()
// Enable or disable the mechanism globally
.Configure<NetworkSocketOptions>(options =>
{
options.EnableTimeout = true;
})
// Fine-tune the timeout duration
.Configure<TimingWheelOptions>(options =>
{
options.IdleTimeoutMs = 30_000; // Disconnect after 30 seconds of silence
options.TickDuration = 1000; // Check once per second
})
.BindTcp<MyProtocol>().Bind()
.Build();
await host.RunAsync();
4. Verifying Idle Disconnection¶
When the timing wheel disconnects a client, it emits a Debug or Info level log (depending on your logging configuration).
Example Log Output:
[DEBUG] [NW.TimingWheel] timeout remote=192.168.1.50 idle=30005ms
[INFO] [NW.TcpListenerBase] close=192.168.1.50
Pro-Tip: TCP Keep-Alive¶
Idle timeout detects application-level silence. To detect network-level dead sockets (where the client crashed without closing the connection), also ensure KeepAlive is enabled in NetworkSocketOptions.