Create web socket streams between a server and arbitrary NodeJS processes - node.js

Having a server running on localhost:5000, I want to connect to that server from another NodeJS process, via web sockets.
From my experience with web sockets, I always needed the server object to create a web socket server.
var http = require('http');
// create http server
var server = http.createServer(function(req, res) {
// serve files and responses
...
});
// Socket.io server listens to our app
var io = require('socket.io').listen(server);
// Send current time to all connected clients
function sendTime() {
io.sockets.emit('time', { time: new Date().toJSON() });
}
// Send current time every 10 secs
setInterval(sendTime, 10000);
// Emit welcome message on connection
io.sockets.on('connection', function(socket) {
socket.emit('welcome', { message: 'Welcome!' });
socket.on('i am client', console.log);
});
server.listen(3000);
This is a tiny example using socket.io. Without having access to get the server variable (since this server will be deployed some where in the cloud), how can I connect via web sockets to this server?
An ugly solution would be via HTTP requests, but that's not web sockets. I want to keep the connection open and pipe data there.
How can I do that?

You get the socket.io-client module, require() it into your other nodejs server and use that client module from your other server (which will be the client in this case) and connect from that server to this one.
Example code here: https://github.com/automattic/socket.io-client
var socket = require('socket.io-client')('http://localhost');
socket.on('connect', function(){});
socket.on('event', function(data){});
socket.on('disconnect', function(){});

Related

Too many EIO socket.io polling calls slowing the web page

My application is based on Socket.io to have a chat functionality.
My application is deployed on red hat open shift.
I keep getting http://url/socket.io/?EIO=3&transport=polling&t=Lj8huKr&sid=y1OB9OBmdSd_Ma4nAAFG requests which are huge in number.
And they are probably also blocking the loading of my web page which is slowing my web page.
I read in the internet that this error comes if the port is not mentioned. But my port number is coming of red hat open shift configuration page.
Below is the code of how socket.io is intialized in my initial html page the node js initial server page
index.html
var socket =io();
index.js (node js server)
var app = express();
var server = app.listen(process.env.NODE_PORT || 3006, process.env.NODE_IP || 'localhost', function(){
console.log('listening on port 3006');
});
var io = require('socket.io').listen(server);
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
socket.on('chat message', function(msg) {
console.log(msg);
io.emit('chat message', msg);
});
In socket.io-client v1.x, the initial connection will start as polling so you will always see at least some requests to the http://site.url/socket.io/?EIO=3&transport=polling URL.
Socket.io clients will then attempt to upgrade to a websocket connection. Those clients that can't upgrade will remain polling regularly to get as close to real time as they can. If you have a large number of clients that are polling every 2 seconds then you will see a lot of requests.
v2.x+ clients moved to using websockets first, but will fallback to the same long polling a URL if the websocket connection fails.

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 :)

Server showing multiple client connection (net nodejs)

I am trying to make a server which listens on a internet facing port and forwards incoming http requests to an internal express server listening at another port. Following is the relevant part of the code I'm using.
var net = require('net');
var server = net.createServer();
server.listen(addr.from[3], addr.from[2], function(){
console.log('Server listening');
});
server.on('connection',function(from){
console.log('Client connected from '+ from.remoteAddress);
var to = net.createConnection({
host: addr.to[2],
port: addr.to[3]
});
from.pipe(to);
to.pipe(from);
from.on('error',function(err){
winston.error('Error at unix box'+err);
to.end();
});
to.on('error',function(err){
winston.error('Error at middleware server'+err);
from.end();
});
from.on('end',function(){
console.log('Client disconnected ');
to.end();
});
to.on('end',function(){
console.log('Middleware disconnected');
from.end();
});
});
The problem I'm encountering is that, when I open "ip:port" in the browser (which would be the internet facing port) I'm getting messages multiple "client connected from xxxxxx" msgs on the console. Can anyone help me understand why this is happening?
Whenever browser connects to a website it usually makes two requests: normal and to retrieve favicon.
Funny thing, is that the favicon request is not even displayed in browser developer tools.
To verify, you need to extract the request made, print it to server, and then observe why you get multiple requests. For that, connection might be too early, try hooking request event instead:
server.on('request', funtion(req, res) { console.log(req.url); });

NodeJS connect to wss on another server

There is a wss on another server that I'd like to connect to. Let's say its address is: wss://123.123.123.12:8843
I have a nodejs/expressjs app. How do I connect to it using socket.io? I know how to implement socket.io for a server/client setup, but how do I do it for two servers (one of which I don't have access to).
How do I setup my expressjs app to connect to the wss? Is there a way using socket.io or do I need to do it another way?
Socket.IO isn't a WebSocket. It is a transport system that supports WebSockets, but if you want to interface with other WebSockets, you'd have better luck using the ws module, which Socket.IO uses internally. This is how it's used:
var WebSocket = require('ws');
var ws = new WebSocket('ws://www.host.com/path');
ws.on('open', function() {
ws.send('something');
});
ws.on('message', function(data, flags) {
// flags.binary will be set if a binary data is received
// flags.masked will be set if the data was masked
});
If you actually just want to communicate with another Socket.IO server, then install the client on the server. It's used the same way as you would use with a browser client.
npm install socket.io-client
And then usage:
var socket = require('socket.io')('http://host/path');
socket.on('connect', function() {
socket.on('event', function(data) { });
socket.on('disconnect', function() { });
});

Socket.io fires connect event just after the second connect

I'm using socket.io with the latest version of node.js and socket.io shows an curious behavior:
The connect event fires on client side but not on server side for the first time.
After a reload or simply loading the page again the event got fired on both - client and server - side correctly.
What's wrong (with my code?)?
// Client
var socket = io.connect(window.location.protocol + '//' + window.location.hostname, {
'sync disconnect on unload': true
});
socket.on('connect', function() {
alert("Connect");
// Do other stuff
});
-
// Server
io.sockets.on('connection', function(socket) {
console.log("connection");
io.sockets.on('connect', function(socket) {
console.log("connect");
});
});
Started the server and loaded the page:
Client fires the alert, server just logs connection. Now loading the page again, it logs both connection and connect.
Update:
It seems that just the very first connection has such issues, afterwards it works everywhere as expected. Just after every node server (re)start, that behavior appears.
Note: node itself delivers the page where the socket.io is used and that works even on the first request, so a node issue should be excluded then.
Browser is also doesn't matter, it's the same on every browser.
For Socket.IO, connection is the server-side equivalent of connect on the client side. Therefore, when you're inside the callback for the connection event, the socket has already established a connection and you don't need to listen on some other event. I'm not sure what connect on the server side is, but it is not documented and does not work.
// on the server
io.sockets.on('connection', function(socket) {
// this connection has already been established
// no other handler is required
});
// on the client
var socket = io.connect();
socket.on('connect', function() {
// the connection has been established
});

Resources