A real-time WebSocket messaging server built with Node.js, Express, Socket.IO, Redis, and MySQL. EchoWave supports multi-cluster deployments, persistent chat history, and automatic device registration.
- Features
- Architecture
- Prerequisites
- Installation
- Configuration
- Running the Server
- API Documentation
- Web Client
- Android Client
- Database Schema
- Project Structure
- Technologies
- Contributing
- License
- Real-time Messaging: Instant message delivery using WebSocket (Socket.IO)
- Multi-Cluster Support: Horizontal scaling with Redis pub/sub adapter
- Persistent Storage: Chat history saved in MySQL database
- Auto Device Registration: Automatic device ID generation using Faker.js
- Broadcast Messaging: Send messages to all connected devices
- Chat History: Load previous messages on connection
- Connection Management: Track user connections and disconnections
- Web Interface: Modern responsive chat UI with AngularJS and Bootstrap
- Cross-Platform: Compatible with web browsers and Android app
βββββββββββββββ βββββββββββββββ
β Client 1 β β Client 2 β
ββββββββ¬βββββββ ββββββββ¬βββββββ
β β
βββββββββ¬ββββββββββββββββ
β WebSocket
βββββββββΌββββββββ
β Socket.IO β
β Server β
βββββ¬ββββββββ¬ββββ
β β
βββββββββΌβββ ββββΌββββββββ
β MySQL β β Redis β
β Database β β Pub/Sub β
ββββββββββββ ββββββββββββ
Before you begin, ensure you have the following installed:
- Node.js (v14.0.0 or higher)
- npm (v6.0.0 or higher)
- MySQL (v5.7 or higher)
- Redis (v5.0 or higher)
-
Clone the repository
git clone <repository-url> cd EchoWave
-
Install dependencies
npm install
-
Set up environment variables
Create a
.envfile in the root directory:# Database Configuration DB_HOST=localhost DB_USER=root DB_PASSWORD=your_password DB_NAME=echowave_db DB_PORT=3306 # Redis Configuration REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= # Server Configuration PORT=3000
-
Start MySQL and Redis services
Windows:
# Start MySQL net start MySQL80 # Start Redis redis-server
Linux/macOS:
# Start MySQL sudo service mysql start # Start Redis redis-server
-
Database initialization
The database and tables will be created automatically on first run. The server will:
- Create the
echowave_dbdatabase (if it doesn't exist) - Create the
userstable - Create the
messagestable
- Create the
MySQL connection pool configuration:
- Connection limit: 10
- Wait for connections: enabled
- Queue limit: 0 (unlimited)
Redis pub/sub clients for multi-server messaging:
- Publisher client for sending messages
- Subscriber client for receiving messages
npm startThe server will start on http://localhost:3000
NODE_ENV=production npm start# Install PM2 globally
npm install -g pm2
# Start the server
pm2 start bin/www --name echowave
# Monitor
pm2 monit
# Logs
pm2 logs echowave
# Restart
pm2 restart echowave
# Stop
pm2 stop echowave1. register
- Description: Register a new device or authenticate existing device
- Payload:
{ deviceId: string | null, // null for new device deviceName: string | null // Optional device name }
- Response:
{ success: boolean, deviceId: string, deviceName: string, history: Array<Message> // Recent chat history }
2. send_message
- Description: Send a message to specific device or broadcast to all
- Payload:
{ message: string, receiverDeviceId: string | null // null for broadcast }
- Response:
{ success: boolean, messageId: number, error?: string }
3. typing (Optional)
- Description: Notify when user is typing
- Payload:
{ isTyping: boolean }
1. new_message
- Description: Receive new message from another user
- Payload:
{ id: number, message: string, senderDeviceId: string, senderName: string, receiverDeviceId: string | null, timestamp: string, isBroadcast: boolean }
2. user_connected
- Description: Notification when a user connects
- Payload:
{ deviceId: string, deviceName: string }
3. user_disconnected
- Description: Notification when a user disconnects
- Payload:
{ deviceId: string, deviceName: string }
4. typing_status (Optional)
- Description: User typing status
- Payload:
{ deviceId: string, deviceName: string, isTyping: boolean }
GET /
- Home page
- Returns: Express welcome page
GET /chat
- Web chat interface
- Returns: Interactive chat UI with AngularJS
The web interface is built with:
- AngularJS v1.8.2 - MVC framework
- Bootstrap v5.3.8 - UI styling
- Toastr v2.1.4 - Notifications
- Socket.IO Client - WebSocket connection
- β Real-time message sending/receiving
- β Bootstrap-styled responsive design
- β Connection status indicator
- β Message history display
- β Sender name badges
- β Timestamp formatting
- β Toast notifications for events
- Start the server
- Open browser and navigate to:
http://localhost:3000/chat
The Android companion app (Demo_Websocket) provides:
- β Socket.IO Android client integration
- β Room database for local message persistence
- β RecyclerView with custom message adapters
- β LiveData and ViewModel architecture
- β Automatic reconnection handling
- β Device ID storage in SQLite
- Socket.IO Client Android v2.1.0
- Room Database v2.6.1
- ViewModel & LiveData
- RecyclerView
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
device_id VARCHAR(255) UNIQUE NOT NULL,
device_name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);CREATE TABLE messages (
id INT PRIMARY KEY AUTO_INCREMENT,
sender_device_id VARCHAR(255) NOT NULL,
receiver_device_id VARCHAR(255),
message TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_broadcast BOOLEAN DEFAULT FALSE,
FOREIGN KEY (sender_device_id) REFERENCES users(device_id),
FOREIGN KEY (receiver_device_id) REFERENCES users(device_id)
);EchoWave/
βββ bin/
β βββ www # Server entry point
βββ config/
β βββ database.js # MySQL configuration
β βββ redis.js # Redis pub/sub setup
βββ public/
β βββ images/ # Static images
β βββ javascripts/ # Client-side JS
β βββ stylesheets/
β βββ style.css # Custom styles
βββ routes/
β βββ index.js # Main routes
β βββ users.js # User routes
βββ socket/
β βββ socketHandler.js # Socket.IO event handlers
βββ views/
β βββ chat.ejs # Chat interface
β βββ error.ejs # Error page
β βββ index.ejs # Home page
βββ .env # Environment variables
βββ app.js # Express app configuration
βββ package.json # Dependencies
βββ README.md # This file
- Node.js - Runtime environment
- Express.js v4.16.1 - Web framework
- Socket.IO v4.8.1 - WebSocket library
- MySQL2 v3.15.3 - Database driver
- Redis v5.9.0 - In-memory data store
- @socket.io/redis-adapter v8.3.0 - Multi-server support
- @faker-js/faker v10.1.0 - Fake data generation
- dotenv v16.4.7 - Environment variables
- EJS v2.6.1 - Template engine
- AngularJS v1.8.2 - JavaScript framework
- Bootstrap v5.3.8 - CSS framework
- jQuery v3.7.1 - DOM manipulation
- Toastr v2.1.4 - Notification library
- Socket.IO Client - Real-time communication
- Socket.IO Android Client v2.1.0
- Room v2.6.1 - Local database
- Gson v2.10.1 - JSON parsing
-
Add event handler in
socket/socketHandler.js:socket.on('your_event', async (data, callback) => { // Handle event callback({ success: true }); });
-
Update client code to emit/listen for the event
To modify the database schema:
- Update table definitions in
config/database.js - Restart the server (or manually run SQL migrations)
Add new routes in routes/index.js:
router.get('/your-route', function(req, res, next) {
res.render('your-view', { title: 'Your Title' });
});- Start the server
- Open multiple browser tabs at
http://localhost:3000/chat - Send messages and verify they appear in all tabs
- Check MySQL database for stored messages
- Test Android app connectivity
# Check MySQL database
mysql -u root -p
USE echowave_db;
SELECT * FROM users;
SELECT * FROM messages;
# Check Redis connections
redis-cli
PING
CLIENT LIST1. "Cannot connect to MySQL"
- Ensure MySQL service is running
- Verify credentials in
.envfile - Check if port 3306 is available
2. "Redis connection failed"
- Start Redis server:
redis-server - Verify Redis is running:
redis-cli PING - Check REDIS_HOST and REDIS_PORT in
.env
3. "Port 3000 already in use"
- Change PORT in
.envfile - Or kill the process using port 3000:
# Windows netstat -ano | findstr :3000 taskkill /PID <PID> /F # Linux/macOS lsof -ti:3000 | xargs kill -9
4. "Socket.IO connection failed"
- Check if server is running
- Verify WebSocket URL in client code
- Check firewall settings
- Ensure CORS is properly configured
-
Use PM2 for clustering:
pm2 start bin/www -i max
-
Enable Redis persistence:
- Configure
redis.conffor RDB or AOF
- Configure
-
MySQL indexes:
- Indexes are already on
device_idand foreign keys - Add composite indexes if needed
- Indexes are already on
-
Connection pooling:
- Adjust
connectionLimitinconfig/database.js
- Adjust
- Use environment variables for sensitive data
- Implement authentication/authorization
- Validate and sanitize user input
- Use HTTPS in production
- Enable Redis authentication
- Restrict MySQL user permissions
- Implement rate limiting
- Add CORS whitelist for production
This project is licensed under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
For issues, questions, or suggestions, please open an issue on GitHub.
Made with β€οΈ using Node.js, Socket.IO, and Redis