Example Path: examples/TCP/TcpKeepAliveMultiple
TCP Multi-Socket Server with Keep-Alive
A robust TCP server implementation that handles multiple concurrent connections with automatic dead connection detection using TCP keep-alive mechanisms.
Overview
This application demonstrates a production-ready TCP server that can:
- Handle up to 10 simultaneous TCP connections
- Automatically detect and close dead/disconnected clients
- Implement TCP keep-alive to prevent resource waste from zombie connections
- Use efficient I/O multiplexing with select() for scalable connection management
- Serve a live web page that shows each active connection and its keep-alive state
Features
Multi-Socket Connection Handling
- Concurrent Connections: Supports up to 10 simultaneous TCP connections
- Non-blocking I/O: Uses select() for efficient multiplexing of multiple sockets
- Dynamic Connection Management: Automatically accepts new connections and manages connection slots
Keep-Alive Mechanism
- Idle Detection: Monitors connections for inactivity (default: 5 seconds)
- Automatic Probing: Sends keep-alive packets to idle connections
- Dead Connection Cleanup: Closes connections that don't respond to keep-alive probes (timeout: 3 seconds)
- Resource Protection: Prevents server resource exhaustion from zombie connections
Connection Monitoring
- Real-time Status: Displays connection events, data transfers, and keep-alive activities
- Client Information: Shows client IP addresses and port numbers
- Debug Output: Comprehensive logging of connection lifecycle events
Configuration
Server Settings
#define listenPort (23)
#define maxConnections (10)
#define readBufferSize (1024)
Keep-Alive Timers
#define keepAliveTimeout (5 * TICKS_PER_SECOND)
#define keepAliveResponseTimeout (3 * TICKS_PER_SECOND)
Usage
Starting the Server
- Compile and deploy the application to your NetBurner device
- The server automatically starts listening on port 23 (Telnet)
- Monitor the console for connection status and debug information
Connecting Clients
# Connect using telnet
telnet <device_ip> 23
# Or using netcat
nc <device_ip> 23
Client Commands
- Send any data: Resets the keep-alive timer and echoes confirmation
- Send 'Q' or 'q': Gracefully disconnects from the server
- Stay idle: Triggers keep-alive mechanism after 5 seconds
Web Interface
Alongside the TCP server, the application starts the NetBurner web server and serves a status page from the device's filesystem. Browse to:
The page shows a Live Connections table – one row per active client with its slot, IP:port, idle time, and keep-alive state (Active, or "Probe sent, awaiting response") – plus the server and keep-alive settings. The table is rendered on the device: a <!--CPPCALL ShowConnections --> tag in html/index.html hands the HTTP socket to the ShowConnections() function in main.cpp, which writes each row straight into the page with fdprintf. The page auto-refreshes every five seconds, so opening or dropping a telnet session is reflected in the browser as it happens.
The page uses a self-contained stylesheet (plain CSS, no framework or CDN) so it renders on a closed network with no external dependencies.
Because the web server runs in its own task while the main task adds and removes connections, the two share the connection arrays under an OS_CRIT critical section. The handler takes a quick snapshot of the live connections while holding the lock, then releases it before writing the HTML – so the lock is never held across the (potentially blocking) socket write.
How It Works
Connection Lifecycle
- Accept: New connections are accepted and assigned to available slots
- Monitor: Each connection is monitored for data activity using select()
- Keep-Alive: Idle connections receive keep-alive probes
- Cleanup: Dead or disconnected clients are automatically removed
Keep-Alive Process
- Idle Detection: Server tracks last received data timestamp for each connection
- Probe Transmission: After 5 seconds of inactivity, a TCP keep-alive packet is sent
- Response Monitoring: Server waits up to 3 seconds for any TCP-level response
- Connection Termination: Connections that don't respond are closed and removed
TCP Stack Integration
Testing Scenarios
Normal Operation
# Connect and send data
telnet <device_ip> 23
> hello
Data received
> Q
Goodbye!
Keep-Alive Testing
- Connect to the server but don't send any data
- After 5 seconds, observe keep-alive probe message in server console
- Continue to stay idle for 3+ more seconds
- Connection will be automatically closed
Dead Connection Testing
- Connect to the server
- Physically disconnect the network cable or crash the client
- After 8 seconds total (5 + 3), the server will detect and close the dead connection
Error Handling
- Socket Errors: Automatically detected and connections are closed
- Accept Failures: Gracefully handled with appropriate error messages
- Buffer Overflows: Protected by fixed buffer sizes
- Resource Limits: New connections rejected when server is full
Use Cases
Production Applications
- Long-lived Connections: Services that maintain persistent client connections
- Resource Management: Systems with limited connection resources
- Network Monitoring: Applications requiring dead connection detection
- Embedded Systems: Resource-constrained environments needing efficient connection handling
Network Scenarios
- Unreliable Networks: Environments with frequent network interruptions
- Mobile Clients: Connections that may drop without proper closure
- Firewall Traversal: Maintaining connections through NAT/firewall devices
- Load Balancing: Backend services requiring connection health monitoring
Performance Considerations
- Memory Usage: Each connection uses approximately 1KB for read buffers plus keep-alive tracking
- CPU Overhead: Minimal - keep-alive checks only run once per second
- Network Traffic: Keep-alive probes are small TCP packets sent only when needed
- Scalability: Can be extended to support more connections by increasing maxConnections
Dependencies
Customization
Timeout Values
Adjust the keep-alive timing constants for your specific application requirements:
- Shorter timeouts for faster dead connection detection
- Longer timeouts for reduced network overhead
Connection Limits
Modify maxConnections based on available system resources and application needs.
Troubleshooting
Common Issues
- "Server Full" message: All connection slots are occupied
- Immediate disconnections: Check network connectivity and firewall settings
- Keep-alive not working: Verify TCP stack support and timing configuration
Debug Output
The application provides detailed console output for monitoring:
- Connection establishment and termination
- Keep-alive probe transmission and responses
- Error conditions and socket states