MWIN
A Concurrent Chat System in Go: A self-hosted, terminal-based chat room application showcasing Go's powerful concurrency features.
Introduction
MWIN emerged from a desire to explore Go's networking and concurrency capabilities while building something genuinely useful. The project represents a deep dive into concurrent programming patterns, real-time communication protocols, and terminal user interface design. The motivation was simple: create a chat system that could handle multiple users simultaneously without blocking, while providing a rich terminal-based interface that feels modern and responsive.
Key Features
Multi-User Chat
Supports unlimited concurrent users with real-time message broadcasting using Go channels and goroutines.
Real-Time Messaging
Instant message delivery with custom TCP protocol, connection pooling, and automatic client cleanup.
Terminal User Interface
Rich TUI built with Bubble Tea, featuring scrollable chat history, input handling, and responsive layout.
macOS Notifications
Native system notifications for new messages when the application is in the background.
Technical Implementation
Concurrency Model
The heart of MWIN lies in its sophisticated use of Go's concurrency primitives. Each client connection is handled in its own goroutine, allowing the server to manage hundreds of simultaneous users without blocking. This design showcases one of Go's greatest strengths: making concurrent programming both safe and efficient.
// Main server loop handling concurrent connections
func (s *Server) handleConnection(conn net.Conn) {
defer conn.Close()
client := &Client{
conn: conn,
name: "",
room: s.lobby,
server: s,
}
// Add client to the room
client.room.addClient(client)
// Handle incoming messages in a goroutine
go func() {
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
message := scanner.Text()
s.handleMessage(client, message)
}
}()
// Keep connection alive
select {}
}
Networking Protocol
MWIN implements a simple but robust TCP-based protocol. The broadcasting mechanism uses Go channels to coordinate message delivery across multiple clients. Each broadcast operation spawns goroutines for parallel delivery, with timeout handling to automatically clean up dead connections.
// Broadcasting messages using Go channels
func (r *Room) broadcast(message string, sender *Client) {
r.mu.RLock()
defer r.mu.RUnlock()
// Create a channel for coordinating broadcasts
done := make(chan bool, len(r.clients))
for client := range r.clients {
if client != sender {
// Send to each client concurrently
go func(c *Client) {
defer func() { done <- true }()
select {
case <-time.After(5 * time.Second):
// Timeout - remove dead client
r.removeClient(c)
default:
fmt.Fprintf(c.conn, "%s\n", message)
}
}(client)
}
}
// Wait for all broadcasts to complete
for i := 0; i < len(r.clients)-1; i++ {
<-done
}
}
System Architecture
MWIN's architecture demonstrates enterprise-level design patterns applied to a real-time communication system. The modular design separates concerns cleanly, making the codebase maintainable and extensible.
Component Breakdown
- Server Core: Manages TCP connections, client lifecycle, and message routing using Go's net package and concurrent patterns.
- Room Manager: Handles chat room logic, user management, and message broadcasting with thread-safe operations.
- Client Handler: Manages individual client connections, message parsing, and protocol compliance.
- TUI Engine: Renders the terminal interface, handles user input, and manages application state using Bubble Tea.