A production-ready WebSocket-based broadcast server and client written in Go. This project enables real-time bidirectional communication between multiple clients through a central server.
- 🚀 Real-time WebSocket communication
- 🔄 Automatic message broadcasting to all connected clients
- 🛡️ Graceful client connection/disconnection handling
- 📊 Health check and stats endpoints
- ⚙️ Configurable connection limits
- 🧪 Comprehensive unit and integration tests
- 📦 CLI-based interface for easy usage
- 🔐 Connection pooling and resource management
┌─────────┐ ┌─────────────┐ ┌─────────┐
│ Client 1│◄────────┤ ├────────►│ Client 2│
└─────────┘ │ Broadcast │ └─────────┘
│ Server │
┌─────────┐ │ (Hub) │ ┌─────────┐
│ Client 3│◄────────┤ ├────────►│ Client N│
└─────────┘ └─────────────┘ └─────────┘
The server uses a Hub pattern to manage connections:
- Hub maintains a registry of all active clients
- When a message arrives, the Hub broadcasts it to all clients
- Clients run independent read/write goroutines for concurrent I/O
- Go 1.21 or higher
- Make (optional, for using Makefile commands)
# Clone the repository
git clone https://github.com/letsmakecakes/broadcast-server.git
cd broadcast-server
# Install dependencies
make install
# Build the application
make build# Start server on default port (8080)
./broadcast-server start
# Start server on custom port
./broadcast-server start --port 9090
# Start server on custom host and port
./broadcast-server start --host 0.0.0.0 --port 3000# Connect to default server (localhost:8080)
./broadcast-server connect
# Connect to custom server
./broadcast-server connect --server ws://example.com:8080/ws
# Connect with a username
./broadcast-server connect --username Alice# Run server
make run-server
# Run client
make run-client
# Run tests
make test
# Run only unit tests
make test-unit
# Run only integration tests
make test-integration
# Generate coverage report
make test-coverage
# Format code
make fmt
# Run linter
make lintDefault configuration can be customized in internal/config/config.go:
Server:
Host: "localhost"
Port: "8080"
ReadTimeout: 10s
WriteTimeout: 10s
MaxClients: 100
Client:
ServerURL: "ws://localhost:8080/ws"
ReconnectDelay: 5s
MaxRetries: 3
- URL:
/ws - Protocol: WebSocket
- Description: Main endpoint for client connections
- URL:
/health - Method: GET
- Response:
200 OK
- URL:
/stats - Method: GET
- Response: JSON with server statistics
{
"connected_clients": 5,
"max_clients": 100,
"uptime": "1h30m"
}Messages are exchanged in JSON format:
{
"type": "text",
"content": "Hello, World!",
"sender": "Alice",
"timestamp": "2024-01-08T10:30:00Z"
}text- Regular chat messagejoin- User joined notificationleave- User left notificationsystem- System messageerror- Error message
The project includes comprehensive tests:
Located in *_test.go files alongside source code. Test individual components in isolation.
# Run all unit tests
make test-unit
# Run tests for specific package
go test -v ./pkg/protocol/
go test -v ./internal/server/Located in test/integration/. Test the complete system end-to-end.
# Run integration tests
make test-integration
# Skip integration tests
go test -short ./...# Generate coverage report
make test-coverage
# View coverage in browser
open coverage.htmlbroadcast-server/
├── cmd/
│ └── broadcast-server/
│ └── main.go # CLI entry point
├── internal/
│ ├── server/
│ │ ├── server.go # HTTP server & WebSocket handling
│ │ ├── server_test.go # Server tests
│ │ ├── hub.go # Connection hub/manager
│ │ └── client.go # Client connection handler
│ ├── client/
│ │ ├── client.go # WebSocket client
│ │ └── client_test.go # Client tests
│ └── config/
│ └── config.go # Configuration
├── pkg/
│ └── protocol/
│ ├── message.go # Message definitions
│ └── message_test.go # Protocol tests
├── test/
│ └── integration/
│ └── integration_test.go # E2E tests
├── Makefile # Build automation
├── go.mod # Go module definition
├── go.sum # Dependency checksums
├── LICENSE # MIT license
└── README.md # This file
- Create a feature branch
- Implement feature with tests
- Run
make testto verify - Run
make fmtandmake lint - Submit pull request
- Follow standard Go conventions
- Run
gofmtbefore committing - Add tests for new functionality
- Document exported functions and types
Starting broadcast server on localhost:8080
WebSocket endpoint: ws://localhost:8080/ws
Client registered. Total clients: 1
Client registered. Total clients: 2
Client registered. Total clients: 3
$ ./broadcast-server connect --username Alice
Connected to server at ws://localhost:8080/ws
Connected! Type your messages (Ctrl+C to quit):
> Hello everyone!
[10:30:15] Alice: Hello everyone!
[10:30:20] Bob: Hi Alice!
[10:30:25] A new user has joined
[10:30:30] Charlie: Hey folks!
>
- Handles 100+ concurrent connections (configurable)
- Low latency message delivery (< 10 ms typical)
- Efficient memory usage with goroutine pooling
- Automatic cleanup of disconnected clients
- Ensure server is running:
./broadcast-server start - Check firewall settings
- Verify the correct port is being used
- Increase
MaxClientsin configuration - Check for zombie connections
- Restart the server to clear connections
- Verify the WebSocket connection is active
- Check network connectivity
- Review server logs for errors
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Submit a pull request
This project is licensed under the MIT License – see the LICENSE file for details.
- Built with Gorilla WebSocket
- CLI powered by Cobra
- Testing with Testify
- Authentication and authorization
- Message persistence and history
- Private messaging between clients
- Message encryption (TLS/SSL)
- Rooms/channels support
- Rate limiting
- Prometheus metrics
- Docker support
- Kubernetes deployment configs
For questions or feedback, please open an issue on GitHub.
Happy Broadcasting! 🚀