TCP Streaming Architecture
TCP Streamer uses a dedicated network thread to transmit audio data:Socket Configuration (socket2)
The application uses thesocket2 crate for advanced socket control (audio.rs:706-740):
Socket Creation
Send Buffer Size
TCP Keepalive
- Detects dead connections (network cable unplugged)
- Prevents firewall timeout (keeps NAT entries alive)
- Faster failure detection than default OS settings (usually 2 hours)
- After 5 seconds of no data, send TCP keepalive probe
- If no ACK, retry every 2 seconds
- After ~9 probes (OS-dependent), connection marked dead
Type of Service (TOS) / DSCP
| Strategy | DSCP | Hex | Use Case |
|---|---|---|---|
| VoIP | 46 | 0xB8 | Real-time audio (recommended) |
| Low Delay | 16 | 0x10 | Interactive traffic |
| Throughput | 8 | 0x08 | Bulk data transfer |
| Best Effort | 0 | 0x00 | Normal traffic |
TCP Nodelay (Nagle’s Algorithm)
- Nagle buffers small packets to reduce network overhead
- Audio requires immediate transmission (latency-sensitive)
- We already batch data into chunks (128-4096 samples)
- Disabling reduces latency by 40-200ms
Write Timeout (Critical)
write_all()will return error after 5 seconds- Triggers connection cleanup and reconnection
- Prevents “zombie” connections
- Long enough for network jitter
- Short enough to detect server crashes
- Balances responsiveness and stability
Connection Lifecycle
Initial Connection
Reconnection Strategy (Exponential Backoff)
- If 100 clients disconnect simultaneously (server crash)
- Without jitter: All reconnect at same time (thundering herd)
- With jitter: Reconnections spread over ±500ms window
Graceful Shutdown
- Write error detected (
audio.rs:804) - Network thread exits (
audio.rs:960) - User stops stream
- Sends FIN in both directions
- Signals server to close its end
- Prevents half-open connections
Write Error Handling
WouldBlock: Timeout (5s expired)BrokenPipe: Server closed connectionConnectionReset: Server sent RSTNetworkUnreachable: Network failure
- Log error
- Gracefully close socket (send FIN)
- Wait 100ms for kernel cleanup
- Loop continues, triggers reconnection logic
Disconnected Buffer Drain (v1.9.0)
When disconnected, the system drains stale audio to send fresh data on reconnect (audio.rs:613-623):
- During 60-second reconnection delay, 60 seconds of audio accumulates
- Sending old audio on reconnect causes noticeable delay
- Better to send fresh audio immediately
- Avoids blocking network thread for too long
- Balances drain speed and responsiveness
Network Quality Metrics
Jitter Measurement
< 5ms: Excellent (wired network)5-15ms: Good (WiFi)15-50ms: Fair (congested WiFi)> 50ms: Poor (investigate network)
Latency Tracking
- Tracks time spent in
write_all() - Includes kernel buffering and network transmission
- Rolling window of 100 samples
Quality Score (0-100)
90-100: Excellent70-89: Good50-69: Fair< 50: Poor
Thread Priority
- High priority: Reduces jitter under CPU load
- Trade-off: Can starve other processes
- Default: Normal priority (recommended for most users)
Heartbeat Monitoring
- Proves thread is alive
- Provides buffer health visibility
- Helps debug “silent” failures
Network Presets
Three presets optimize for different network conditions:Ethernet
- Ring Buffer: 2000ms
- Chunk Size: 512 samples
- Adaptive Range: 2000-6000ms
- Target: Lowest latency, assumes stable connection
WiFi
- Ring Buffer: 4000ms
- Chunk Size: 1024 samples
- Adaptive Range: 3000-10000ms
- Target: Balanced stability for typical WiFi
WiFi (Poor Signal)
- Ring Buffer: 8000ms
- Chunk Size: 2048 samples
- Adaptive Range: 5000-15000ms
- Target: Maximum stability, prevents dropouts
Future Enhancements
- UDP mode: Lower latency, optional packet loss
- QUIC protocol: Modern alternative to TCP
- Connection pooling: Multiple parallel streams
- SSL/TLS: Encrypted transmission
- IPv6 support: Currently IPv4 only