Socket.io server to server (sending message to specific server) - node.js

I have a specific situation. I have client (browser) which connects to server A. Server A is connected to server B and C. When client sends message to server A, I need to send message to specific server which means to one of the servers B or C, not both of them. Generally I need separated communication between servers but I have only broadcasted communication. Message from server A to another server can't be seen on all connected servers.
How can I send messages directly to one of the servers ? Here is my code snippet for servers. I just change ports for each server and connect them.
// Load requirements
var PORT = process.env.PORT || 8080;//just change port for other servers
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
app.use(express.static(__dirname + '/public'));
var client = require('socket.io-client');
var socket1 = client.connect('http://localhost:8081', { reconnect: true });//connection to server B
var socket2 = client.connect('http://localhost:8082', { reconnect: true });//connection to server C
// Add a connect listener
io.on('connection', function (socket) {
console.log('Client connected.');
//when server receive message from client
socket.on('message_from_browser', function (message) {
console.log("Message from browser broadcasted: " + message.text);
var updated_message = {
text: message.text,
port: PORT
};
// send message to server B
socket1.emit('server_message', updated_message);//send message to server B
});
// Disconnect listener
socket.on('disconnect', function () {
console.log('Client disconnected.');
});
});
socket1.on('connect', function () {
socket1.on('server_message', function (message) {
console.log('RECEIVED MESSAGE FROM ANOTHER SERVER ON PORT '+ message.port + ": " + message.text);
});
//change server name
console.log('Connected to server B!');
});
socket2.on('connect', function () {
socket2.on('server_message', function (message) {
console.log('RECEIVED MESSAGE FROM ANOTHER SERVER ON PORT '+ message.port + ": " + message.text);
});
//change server name
console.log('Connected to server C!');
});
http.listen(PORT, function (req, res) {
console.log("Server Started on port: " + PORT);
});

You have a naming conflict with the variable name socket. It is defined as both your connection to server B and as an argument in your .on('connection', function(socket) {...}) callback.
To fix that, change this:
var socket = client.connect('http://localhost:8081', { reconnect: true });//connection to server B
var socket2 = client.connect('http://localhost:8082', { reconnect: true });//connection to server C
To this:
var socket1 = client.connect('http://localhost:8081', { reconnect: true });//connection to server B
var socket2 = client.connect('http://localhost:8082', { reconnect: true });//connection to server C
And, then refer to the server B connection as socket1, not socket.
The variable named socket is already defined as an argument in this so you cannot reach the outer socket variable when it has a conflicting name:
// Add a connect listener
io.on('connection', function (socket) {
// socket variable name ^^^^^^
console.log('Client connected.');
//when server receive message from client
socket.on('message_from_browser', function (message) {
console.log("Message from browser broadcasted: " + message.text);
var updated_message = {
text: message.text,
port: PORT
};
// send message to server B
socket1.emit('server_message', updated_message);//send message to server B
});
// Disconnect listener
socket.on('disconnect', function () {
console.log('Client disconnected.');
});
});
And there were no listeners for incoming server messages so you need to add listeners for socket1 and socket2.
io.on('connect', function(socket1){
socket1.on('server_message', function (message) {
console.log('RECEIVED MESSAGE FROM ANOTHER SERVER ON PORT '+ message.port + ": " + message.text);
});
});
io.on('connect', function(socket2){
socket2.on('server_message', function (message) {
console.log('RECEIVED MESSAGE FROM ANOTHER SERVER ON PORT '+ message.port + ": " + message.text);
});
});

Use one variable and configs to track others hosts, try:
Updated to fix some bugs:
// Load requirements
var PORT = process.env.PORT || 8081;//just change port for other servers
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
var async = require('async'); // async is optional for this example ...
var client = require('socket.io-client');
app.use(express.static(__dirname + '/public'));
// save hosts here ...
var otherServers = {
server1: {
url: 'http://localhost:8082'
},
server2: {
url: 'http://localhost:8083'
},
};
// Add a connect listener
io.on('connection', function (socket) {
console.log('Client connected.');
//when server receive message from client
socket.on('message_from_browser', function (message) {
console.log("Message from browser broadcasted: " + message.text);
var updated_message = {
text: message.text,
port: PORT
};
// choice how server will receive this message ...
// then send it
otherServers.server1.client.broadcast.emit('server_message', updated_message);
});
// Disconnect listener
socket.on('disconnect', function () {
console.log('Client disconnected.');
});
});
async.each(otherServers, function forEachOtherServer(otherServer, next) {
//connect to another server
otherServer.client = client.connect(otherServer.url, { reconnect: true });
// to something more if need in every client connection ...
otherServer.client.on('connect', function (x) {
otherServer.client.on('server_message', function (message) {
console.log('RECEIVED MESSAGE FROM ANOTHER SERVER ON PORT '+ message.port + ": " + message.text);
//socket.broadcast.emit('message_from_server', message_server);
});
console.log('Connected!');
});
next();
}, function afterConnectInAllServers(err) {
if (err) throw err;
// to something after connect in all servers ...
});
http.listen(PORT, function (req, res) {
console.log("Server Started on port: " + PORT);
});

Related

Forward Android TCP Connection to HTTP proxy in Node.js

My plan is to create a proxy of my phone 4g connection.
I've made a direct tcp connection of my phone to my pc via nodejs.
I create a client.js on my phone and server.js on my pc. They connect.
Now i need to 'transform' this direct connection into a proxy, but i dont know how.
Any help i would aprecciate.
I will show my server.js and client.js code below.
Server.js
var net = require('net');
var tcpServerPort = 7000;
// a simple TCP server for testing
var server = net.createServer(function (socket) {
console.log('Client connected to server');
socket.on('close', function () {
console.log('Client disconnected from server');
});
socket.on('data', function (buffer) {
// 'echo' server
socket.write(buffer);
});
socket.on('error', function (err) {
console.log('Error: ' + err.soString());
});
});
server.listen(tcpServerPort);
Client.js
const net = require('net');
const client = new net.Socket();
const port = 7000;
const host = 'my home ip';
client.connect(port, host, function() {
console.log('Connected');
client.write("Hello From Client " + client.address().address);
});
client.on('data', function(data) {
console.log('Server Says : ' + data);
});
client.on('close', function() {
console.log('Connection closed');
});

Talking AWS Servers (EC2)

I am trying to get two EC2 instances to talk; but, I am running into a block. I am not sure what IP address and port to use, and also am wondering if I need to change any of the server/client code now that they aren't talking on the same machine. Security Groups are allowing inbound traffic on ports 22,80, and 60201.
When I use port 60201, i get EADDRNOTAVAIL.
Here is the config file.
Host wmnode
User ubuntu
IdentityFile ~/.ssh/wmnode
HostName 52.4.212.112
Host mvclient
User ubuntu
IdentityFile ~/.ssh/mvclient
HostName 107.21.65.254
Here is server.js
const port = 60201;
const ipAddress = "52.4.212.112"
var http = require('http');
var io = require('socket.io');
var server = http.createServer();
server.listen(port, ipAddress);
var socket = io.listen(server);
socket.on('connection', (serverSocket) => {
console.log('connected to 52.4.212.112');
serverSocket.on('clientEvent', function (data) {
console.log('message from the server:', data);
serverSocket.emit('serverEvent', "thanks for sending '" + data + "'");
});
});
And here is client.js
const port = 60201;
const ipAddress = "52.4.212.112";
const url = 'http://' + ipAddress + ':' + port;
var io = require('socket.io-client');
var socket = io(url);
socket.on('connect', () => {
socket.on('serverEvent', function (data) {
console.log('new message from the server:', data);
});
setInterval(function () {
socket.emit('clientEvent', Math.random());
console.log('message sent from the client');
}, 3000);
});

socket.io connection still exists after disconnection

I am trying to forward message from Redis pubsub to socketio client by using nodejs EventEmitter.
var events = require('events');
var subscriber = redis.createClient();
var app = express();
var localEmitter = new events.EventEmitter();
var server = require('http').createServer(app);
var io = require("socket.io")(server, {secure: 'true'});
io.on('connection', function (socket) {
localEmitter.on('FORWARDING', function(message)) {
console.log(socket.id + ': localEmitter is forwarding messages');
}
socket.on('disconnect', function(){
console.log(socket.id + ' disconnected);
})
};
subscriber.on('message', function (channel, message) {
console.log("Got message from redis");
localEmitter.emit('FORWARDING', encoded);
});
But if I refresh the webpage, the websocket connection disconnects and reconnects, the disconnect method can be triggered, but the localEmitter still forwarding messages via the old socket id.
The logs look like:
pxw8pcocxI3O2ru3AAAA: localEmitter is forwarding message
0BX2bVYoAn2g2JtMAAAB: localEmitter is forwarding message
0BX2bVYoAn2g2JtMAAAB disconnected
pxw8pcocxI3O2ru3AAAA: localEmitter is forwarding message
0BX2bVYoAn2g2JtMAAAB: localEmitter is forwarding message
...
Remove event emitter when socket disconnects
io.on('connection', function(socket) {
localEmitter.on('FORWARDING', mymessage);
function mymessage(message) {
console.log(socket.id + ': localEmitter is forwarding messages');
}
socket.on('disconnect', function() {
localEmitter.removeListener('FORWARDING', mymessage);
console.log(socket.id + ' disconnected');
});
});
You can also use the concept of room for the same.

How to emit message from client side [node.js + socket.io]

I am trying to emit message from client side with socket.io ...
Here is my client code:
var socket = io.connect('http://localhost/');
socket.on('connect', function(data){
setStatus('connected');
socket.emit('subscribe', {channel:'update.comment'});
});
Server:
io.sockets.on('connection', function (socket) {
socket.emit('message', { text : 'Welcome!' });
socket.on('subscribe', function (data) {
socket.join(data.channel);
redisClient.subscribe(data.channel);
});
});
Also I get this error message in console:
GET
http://localhost/socket.io?EIO=3&transport=polling&t=1442169984269-1
404 (Not Found)
Full serever:
var app = require('express')();
var http = require('http').Server(app);
var redis = require('ioredis');
var io = require('socket.io')(http);
redisClient = redis.createClient();
//look for connection errors and log
redisClient.on("error", function (err) {
console.log("error event - " + redisClient.host + ":" + redisClient.port + " - " + err);
});
io.sockets.on('connection', function (socket) {
socket.emit('message', { text : 'Welcome!' });
//on subscription request joins specified room
//later messages are broadcasted on the rooms
socket.on('subscribe', function (data) {
socket.join(data.channel);
redisClient.subscribe(data.channel);
});
});
redisClient.on('ready', function(data) {
console.log('#redis ready');
});
redisClient.on("message", function(channel, message){
console.log(channel);
var resp = {'text': message, 'channel':channel};
io.sockets.in(channel).emit('message', resp);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
New Problem Recognized:
Your server is listening on port 3000, but you are attempting to connect on port 80. The error message http://localhost/socket.io?EIO=3&transport=polling&t=1442169984269-1 has no port number on it so that defaults to port 80.
That error message means that your server-side socket.io code is not initialized correctly and thus is not listening for the HTTP request that starts all webSocket connections so when the browser tries to connect on that URL to initiate a socket.io connection, there's nobody on the server-side listening so the web server returns a 404 error back to the browser.
If you are using Express, this is the minimal socket.io initialization to hook it into your server:
var express = require('express');
var app = express();
var server = app.listen(8081);
var io = require('socket.io').listen(server);
For a plain HTTP server, this is the minimal socket.io initialization:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
app.listen(80);
As always, if you show us the socket.io and web server initialization code you are using, we can help you better with your specific code issue.

node.js listen for UDP and forward to connected http web clients

I'm new to node.js, so forgive the ignorance if this is simple.
What I want to do is setup a simple node.js http server to which a web-client connects. I also want the node.js server to act as a UDP listener on a separate port, on which it will receive JSON payloads from some other application. I want the node.js server to then forward these JSON payloads immediately to one or more of the connected web-clients.
I got this far from some initial googling around:
Create a simple node.js http server that responds with a static html page:
//Initialize the HTTP server on port 8080, serve the index.html page
var server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/index.html'));
}).listen(8080, function() {
console.log('Listening at: 127.0.0.1 8080');
}
);
Initialize a UDP server on a separate port:
//Initialize a UDP server to listen for json payloads on port 3333
var srv = dgram.createSocket("udp4");
srv.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
io.sockets.broadcast.emit('message', 'test');
//stream.write(msg);
//socket.broadcast.emit('message',msg);
});
srv.on("listening", function () {
var address = srv.address();
console.log("server listening " + address.address + ":" + address.port);
});
srv.bind(5555);
Use socket.io to establish a live connection between web-client and server:
//this listens for socket messages from the client and broadcasts to all other clients
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
socket.on('message', function (msg) {
console.log('Message Received: ', msg.data.skeletons[0] ? msg.data.skeletons[0].skeleton_id : '');
socket.broadcast.emit('message', msg);
}
);
});
I guess my problem is I don't know how to bridge 2 and 3, to get the received UDP packets broadcasted to the connected socket.io clients. Or perhaps there's a simpler, more elegant way of doing this? I found the documentation for socket.io to be lacking...
EDIT: thanks to the person that fixed the code formatting
I made a running example for you to get going with: http://runnable.com/UXsar5hEezgaAACJ
For now it's just a loopback client -> socket.io -> udp client -> udp server -> socket.io - > client.
here's the core of it:
var http = require('http');
var fs = require('fs');
var html = fs.readFileSync(__dirname + '/index.html');
//Initialize the HTTP server on port 8080, serve the index.html page
var server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'
});
res.end(html);
}).listen( process.env.OPENSHIFT_NODEJS_PORT, process.env.OPENSHIFT_NODEJS_IP, function() {
console.log('Listening');
});
var io = require('socket.io').listen(server);
io.set('log level', 0);
io.sockets.on('connection', function (socket) {
socket.emit('message', 'connected');
socket.on('message', function (data) {
console.log(data);
var address = srv.address();
var client = dgram.createSocket("udp4");
var message = new Buffer(data);
client.send(message, 0, message.length, address.port, address.address, function(err, bytes) {
client.close();
});
});
});
var dgram = require('dgram');
//Initialize a UDP server to listen for json payloads on port 3333
var srv = dgram.createSocket("udp4");
srv.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
io.sockets.emit('message', 'udp');
});
srv.on("listening", function () {
var address = srv.address();
console.log("server listening " + address.address + ":" + address.port);
});
srv.on('error', function (err) {
console.error(err);
process.exit(0);
});
srv.bind();

Resources