I am trying to create a simple chat App with Node.JS and Websocket using Socket.IO. I inspired myself by this German tutorial and for the single backend instance it works well.
I would like to have 2 instances of the server in the backend, which should sync the chat messages between each other and store the chat history in redis. The client should display the last 10 messages from the current channel, when new chat-room is joined.
I tried to apply the solution from this stackoverflow page but I get some issues. First I get
WebSocket connection to 'ws://localhost:8080/socket.io/?EIO=3&transport=websocket&sid=LEqGvY0CVk9YaSzBAAAA' failed: Connection closed before receiving a handshake response
error in the console. And second, both clients are receiving the 'payload' messages in the 1-sec interval. I probably do not understand how the redis-sync mechanism works and I also do not yet know how to display the chat history.
Here is my code so far:
var conf = require('./config.json');
var cluster = require('cluster');
var os = require('os');
if (cluster.isMaster) {
// we create a HTTP server, but we do not use listen
// that way, we have a socket.io server that doesn't accept connections
var server = require('http').createServer();
var io = require('socket.io').listen(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: conf.redisUri, port: conf.redisPort }));
setInterval(function() {
// all workers will receive this in Redis, and emit
io.emit('chat', {time: new Date(), text:'payload'});
}, conf.syncIntervall);
// set number of workers
for (var i = 0; i < conf.numberOfWorkers; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
}
if (cluster.isWorker) {
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var redis = require('socket.io-redis');
// Webserver
//app.listen(conf.defaultPort);
server.listen(conf.defaultPort);
// deliver static files
app.use(express.static(__dirname + '/public'));
// route for the / path
app.get('/', function (req, res) {
// send the index.html in the reponse
res.sendfile(__dirname + '/public/index.html');
});
// Websocket
io.adapter(redis({ host: conf.redisUri, port: conf.redisPort }));
// Callback when a client connects
io.sockets.on('connection', function (socket) {
// store the room name in the socket session for this client
socket.room = 'defaultChannel';
// send client to room 1
socket.join('defaultChannel');
// echo to client they've connected
socket.emit('chat', { time: new Date(), text: 'You have connected to room defaultChannel on the server!' });
socket.emit('chat', { time: new Date(), text: 'Connected to chat worker-node: ' + cluster.worker.id});
// if a message is received
socket.on('chat', function (data) {
// the it will be send to all other clients
console.log('the current channel', socket.room);
socket.broadcast.in(socket.room).emit('chat', { time: new Date(), name: data.name || 'anonymous', text: data.text });
});
// if a client joins a channel
socket.on('join', function (room) {
// store the room name in the socket session for this client
socket.room = room;
// send client to room 1
socket.join(room);
console.log('Client joined room ' + room);
});
});
// Log port number in the console
console.log('Server running under http://127.0.0.1:' + conf.defaultPort + '/');
}