Socket.io on multiple servers with HaProxy - node.js

I have HAProxy which serve multiple servers with nodejs on expressjs. I have added to that express socket.io and to make them work i tried to connect them with socket.io-redis and socket.io-ioredis. All looks to be connected without any error but when an user get his socket connected with different server from other user, their emits don't read don't send to other servers.
Nodejs setup
var app = express();
var server = require('http').Server(app);
var io = require('socket.io').listen(server);
var redis = require('socket.io-ioredis');
io.adapter(redis({ host: 'serverIP', port: 6565 }));
server.listen(6565);
How do i do the emit:
io.to(roomID).emit(event, object);

The actual problem was that port on which redis was connecting in server was blocked by the firewall.

Related

Force node.js socket.io 2.4 to listen to 127.0.0.1

I have a Node.js Socket.io v2.4 server that I want to restrict its access. I want only a particular chrome extension to be able to connect to it and nothing else. I noticed that traffic from Chrome Extension shows up as 127.0.0.1 as opposed to other traffic from localhost shows up as localhost. I know there are other ways like Interprocess Communication (IPC) that might be better than communication over websockets and http, but I can not use those at the moment.
Here are the pertinent parts of the node.js server code:
var express = require('express');
var path = require('path');
var app = express();
var server = require('http').createServer({
requestCert: false,
rejectUnauthorized: false
}, app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
//511 is backlog, which Specifies the max length of the queue of pending connections. Default 511
server.listen(port, '127.0.0.1', 511, function () {
console.log('[server] listening at port %d', port);
});
I thought this would only listen to requests from 127.0.0.1, but it seems to accept requests from any website loading in the browser.
Any help is most appreciated .. thank you

How do I send message to another socket.io server using socket.io-redis?

I need to have two different socket.io servers communicate with each other. I cannot use socket.io-client since it does not differentiate between browser to server connections and server to server connections. So I am trying to use socket.io-redis.
One is an express-socket.io server and another is a standalone socket.io server. Both have been configured to use socket.io-redis adapter. I do not see message received at Server1 from Server2. Also there are no errors.
Server1 :
var express = require('express');
var app = express();
var server = app.listen(8000,function () {
console.log('server listening at port 8000');
});
var io = require('socket.io')(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
io.on('message',function (message) {
console.log(message);
});
io.on('connection',function (socket) {
console.log('connection');
socket.on('message',function (message) {
console.log(message);
});
});
Server2:
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
io.emit('message','Hi');
socket.io-redis will not allow You to capture events from one server on another. How it works is it will simply "push" messages emited by one server to other connected servers, so those can emit those messages to.
If instance A will recieve an event (ie. io.on('connect')), You will not be able to capture that event on instance B. You will however be able to emit a message to all clients connected to all instances, simply by calling
socket.on('message', function(socket){
socket.emit('hello', 'New message');
}
This way You will broadcast the message to all clients, either connected to instance A or B (including Yourself for that matter). This approach allows You to scale out Your application to other instances on one machine (utilize more than one thread) or to other servers.
If You need Your servers to "talk" to each other, You can utilize Your existing transport layer - Express server. You could create handlers for different type of requests, for example:
app.get('/api/clientCount', function(req, res){
res.send(io.engine.clientsCount);
});
This way You can exchange information between socket.io instances, change their state, make all instances report usage, etc. Thing to remember - authenticate requests; You don't want to get those calls from unauthorised users :)

Need for http.createServer(app) in node.js / express

Using node and express, the below works just fine.
var app = express();
app.listen(app.get('port'), function() {
});
I assume that a server is created implicitly in the above construct.
When adding socket.io, I've seen the following being done.
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
app.listen(app.get('port'), function() {
});
What is the need for explicitly adding http.createServer(app) ? Won't the creation of an additional server mess up things ? Or put it other way, is it ok to create many more http.createServer(app) ?
In either case, only one server is created. When using socket.io, you share the same http server between socket.io and express. Both libraries attach event listeners to the same server and have a chance to respond to the same events. They cooperate nicely because socket.io only handles relevant requests and express handles all the non-websocket requests. And just FYI you could not create more than one server on the same port. Only one process can listen on a TCP port at a time in the OS, so the second one would fail with an error when attempting to bind an in-use port.

http server and web sockets from separate servers

It's pretty easy to configure a http server (using express) and a socket server (socket.io) assigned to it:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
How can I run http server and socket server in two different node.js instances?
My idea is to leverage the performance this way, releasing the http node instance from the responsibility of also sending notifications back to the clients.
In a regular Socket.IO + Express app, Socket.IO intercepts requests starting with /socket.io/.
You may set Nginx (or any other webserver that supports proxying) listening 80 port, and make it proxy to Socket.IO process if request starts with /socket.io/, and to Express process otherwise.
Edit: To set up Socket.IO in separate process you may use the following code:
var io = require('socket.io')();
io.on('connection', function(socket){
//here you can emit and listen messages
});
io.listen(3000);

Serving socket.io through SSL

I'd like to implement ssl in all of my projects. One of them is using socket.io.
My code to create the socket:
var server = require('http');
var app = server.createServer(function(request, response) {
response.end();
});
var io = require('socket.io').listen(app);
app.listen(8000);
I can't bind node.js / socket.io to ssl port cause it's already in use by my webserver (cherokee). Therefore i can't serve the client using https.
Any ideas how to solve this problem?
You can only bind one application to a port. Since your web server is already bound to port 443, you have two choices:
Run the web server like you are now and proxy the node.js stuff running on port 8000:
http://www.cherokee-project.com/doc/modules_handlers_proxy.html
Run node.js on that port, change the port of the web server and proxy the web server using node.js: https://github.com/nodejitsu/node-http-proxy

Resources