Node JS Server to Server Connection - node.js

Is it possible to connect to a NodeJS Server from another server? Two NodeJS servers communicating with each other?
//Server Code
var io = require('socket.io').listen(8090);
io.sockets.on('connection', function (socket) {
io.sockets.emit('this', { will: 'be received by everyone'});
socket.on('private message', function (from, msg) {
console.log('I received a private message by ', from, ' saying ', msg);
});
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});
//Client Code in Server Code. Connecting to another server.
io.connect( "http://192.168.0.104:8091" ); //Connect to another server from this one.
//ETC...

Here's a simple example that creates a server and a client that connects to that server. Remember that what you send has to be a buffer (strings are automatically converted to buffers). The client and server works independently of eachother, so can be put in the same app or on totally different computers.
Server (server.js):
const net = require("net");
// Create a simple server
var server = net.createServer(function (conn) {
console.log("Server: Client connected");
// If connection is closed
conn.on("end", function() {
console.log('Server: Client disconnected');
// Close the server
server.close();
// End the process
process.exit(0);
});
// Handle data from client
conn.on("data", function(data) {
data = JSON.parse(data);
console.log("Response from client: %s", data.response);
});
// Let's response with a hello message
conn.write(
JSON.stringify(
{ response: "Hey there client!" }
)
);
});
// Listen for connections
server.listen(61337, "localhost", function () {
console.log("Server: Listening");
});
Client (client.js):
const net = require("net");
// Create a socket (client) that connects to the server
var socket = new net.Socket();
socket.connect(61337, "localhost", function () {
console.log("Client: Connected to server");
});
// Let's handle the data we get from the server
socket.on("data", function (data) {
data = JSON.parse(data);
console.log("Response from server: %s", data.response);
// Respond back
socket.write(JSON.stringify({ response: "Hey there server!" }));
// Close the connection
socket.end();
});
The conn and socket objects both implement the Stream interface.

Check Substrack's dnode. It auto maps literal objects from the 1st env to the 2nd one. You gain a kind of RPC out of the box. And it works in the browser too...

Related

Nodejs socket write to all connections

I have a socket server in node. When it revives a new message, it writes it to the socket. But from which it has revived, writes to the corresponding socket, not all connections.
Server.js
var server = net.createServer(function(sock){
console.log('new client connected');
sock.on('data', function(data) {
console.log('Server received');
// ** NOT sending to all clients **
sock.write('broadcasting to others...');
});
});
Client.js
var client = new net.Socket();
client.connect(PORT, HOST, function() {
console.log('Client connected to: ' + HOST + ':' + PORT);
// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
client.write('Client is connected!!');
});
client.on('data', function(data) {
console.log('Client received: ' + data);
});
How can I broadcast one client message to all other clients?
Following up on my suggestion to use a Set to keep track of all the connected sockets, this is one way to implement that. This implementation maintains that Set as connections come and go by listening to both the connect event and the end event.
This implementation also supports a desirable feature to send to all connected sockets EXCEPT the one that triggered the event (which I think is what your situation would want):
// Set of all currently connected sockets
const connectedSockets = new Set();
// broadcast to all connected sockets except one
connectedSockets.broadcast = function(data, except) {
for (let sock of this) {
if (sock !== except) {
sock.write(data);
}
}
}
const server = net.createServer(function(sock){
console.log('new client connected');
connectedSockets.add(sock);
sock.on('end', function() {
connectedSockets.delete(sock);
});
sock.on('data', function(data) {
console.log('Server received');
connectedSockets.broadcast(data, sock);
});
});
I believe you can always keep the socket reference for each client in an array when they established connection to the server. To broadcast, simply loop the array and use perform the write()
var clients = [];
var server = net.createServer(function(sock){
console.log('new client connected');
clients.push(sock);
sock.on('data', function(data) {
console.log('Server received');
for(var i = 0; i < clients.length; i++) clients[i].write('broadcasting..');
});
});
Or if you have the control on both server and client, I think it is better to use websocket or socket.io as it offer broadcast feature.

Node.js express websocket not broadcasting to all connected clients

Im trying to create a node websocket for messaging and broadcasting using openshift. Below is my code.
var WebSocketServer = require('ws').Server;
var http = require('http');
var ipaddr = opneshift_ip;
var port = openshift_port;
var server = http.createServer();
var wss = new WebSocketServer({server: server, path: '/connectserv'});
wss.broadcast = function(data) {
for(var i in this.clients) {
console.log(this.clients[i]);
this.clients[i].send(data);
}
};
wss.on('connection', function(ws) {
console.log('a client connected');
ws.on('message', function(data) {
console.log('>>> ' + data);
ws.send('got '+data);
if (data == 'broadcst') {
console.log('broadcst');
wss.broadcast('Hi All');
}
});
ws.on('close', function() {
console.log('Connection closed!');
});
ws.on('error', function(e) {
console.log(e);
});
});
console.log('Listening at IP ' + ipaddr +' on port '+port);
server.listen(port,ipaddr);
When any client connects, console writes "a client connected".
When any client sends message, console writes ">>> message" and im getting the same at client as well ("got message")
But when multiple clients are connected, if i want to broadcast a message to all connected clients, i send "broadcst" as message. Than goes into
if (data == 'broadcst') {
console.log('broadcst');
wss.broadcast('Hi All');
}
But only the client which sends get the message.
How to make all clients to get the message?
Does each client creates separate session?
How to use redis here?
Any quick help appreciated.
Thanks.
Try
wss.broadcast = function(data) {
for(var i in wss.clients) {
console.log(wss.clients[i]);
wss.clients[i].send(data);
}
};
broadcasting with wss

Socket.io Redis Server Broadcast

I'm missing something really basic here. I have two very standard express processes with socket io. I'm trying to get a server broadcast on one process to broadcast the same message to another servers clients. I have following setup:
var server = require('http').createServer(app);
var socketio = require('socket.io')(server, {
serveClient: (config.env !== 'production'),
path: '/socket.io-client'
});
require('./config/express')(app);
require('./routes')(app);
server.listen(config.port, config.ip, function () {
logger.info('Express server listening on %d, in %s mode', config.port, app.get('env'));
});
var redis = require('socket.io-redis');
var adapter = redis({ host: config.redis.uri, port: config.redis.port });
adapter.pubClient.on('error', function(){
logger.error('Error on pub client');
});
adapter.subClient.on('error', function(){
logger.error('Error on sub client');
});
socketio.adapter(adapter);
require('./config/socketio')(socketio);
Then my socket io file is:
module.exports = function (socketio) {
//listen to other server broadcasts
socketio.on('socket.io#/#', function(data) {
logger.debug('received message from other process');
});
//client connection code
socketio.on('connection', function (socket) {
socket.address = socket.handshake.address !== null ?
socket.handshake.address + ':' + socket.handshake.address.port :
process.env.DOMAIN;
socket.connectedAt = new Date();
// Call onDisconnect.
socket.on('disconnect', function () {
onDisconnect(socket);
logger.debug('[%s] DISCONNECTED', socket.address);
});
// Call onConnect.
onConnect(socketio, socket);
logger.debug('[%s] CONNECTED', socket.address);
});
};
From a different server I'm just calling a standard emit
socketio.emit('message', object);
In terms of debugging, I load up the redis cli and check the channels that are created:
1) "socket.io#/#"
2) "socket.io-sync#request#/#"
I even run SUBSCRIBE "socket.io#/#" in the cli and can see the message I'm trying to get on the other server displayed via the cli.
This seems so basic, how do I properly subscribe to events on the redis channel 'socket.io#/#'?
EDIT: So I figured out that I receive messages on my other process if I do
socketio.sockets.adapter.subClient.on('message', function (channel, message) {
logger.warn('GOT STUFF ');
});
However here I'm just going straight to the redis sub client. The channel and message are just buffers of non usable data. Isn't this suppose to provide a higher level of abstraction?
EDIT 2: I've got it "mostly" working now. Doing this:
socketio.sockets.adapter.subClient.on('message', function (channel, message) {
logger.warn('GOT STUFF ');
socketio.sockets.in(channel).emit(message);
});
Turns on the socket interface will take the channel and message buffers directly. Now to my next issue, instead of doing socketio.emit(message, doc); I want to do this socketio.sockets.in(doc._id).emit('message;, doc);. Basically i only want it to end in clients that are a part of that room. Doesn't quite seem to be working as is...

node.js server socket.io-client with SSL

I try to setup two node.js servers communication with each other over socket.io. The node servers use SSL, but I don't get it running. I do not get any feedback, its close to this:
Node.js socket.io-client connect_failed / connect_error event
This will not work. No response.
var clientio = require('socket.io-client');
console.log('Trying stuff ...');
// the channel does not exist
var socket = clientio.connect( 'http://localhost:4000/news' );
// I expect this event to be triggered
socket.on('connect_failed', function(){
console.log('Connection Failed');
});
socket.on('connect', function(){
console.log('Connected');
});
socket.on('disconnect', function () {
console.log('Disconnected');
});
but if I try:
// Bind to the news namespace, also get the underlying socket
var ns_news = clientio.connect( 'https://localhost:9000' );
var socket = ns_news.socket
// Global events are bound against socket
socket.on('connect_failed', function(){
console.log('Connection Failed');
});
socket.on('connect', function(){
console.log('Connected');
});
socket.on('disconnect', function () {
console.log('Disconnected');
});
// Your events are bound against your namespace(s)
ns_news.on('myevent', function() {
// Custom event code here
});
I can see that ns_news has no element socket, so I get:
TypeError: Cannot call method 'on' of undefined
So how do I connect these two servers with feedback if the connection is successful or not?
And my following question would be:
How can these two servers authenticate to each other?
Means: Server A says to server B:
- hey, gimme that secret string
And Server B checks the certificate of server A and if it's ok
- here's the string
How do I do it with node?

Can you send a unix domain file descriptor over another unix domain socket in node.js?

In Node.js.
Is it possible to send a unix domain socket file descriptor over already established unix domain socket ?
I have the following example but I am not sure how and if it's even possible to receive the file descriptor on the other end in usable form.
currently getting file descriptor type error on the server side
In the example I have the client connecting to the server side via unix socket and that works fine, then once the connection is established I try to create a new server with new unix socket and pass that file descriptor to the server so server can use it.
Server side:
var net = require('net');
var socket = '/tmp/testing.node.sock';
var fs = require('fs');
if (fs.existsSync(socket)) {
fs.unlinkSync(socket);
}
var server = net.createServer(function(c) {
console.log('server connected');
c.on('end', function() {
console.log('server disconnected');
});
c.on('error', function(e) {
console.log(e);
});
c.on('data', function(data) {
console.log("data received");
console.log(data.toString());
// creating new socket with passed fd
var newsock = new net.Socket({fd:data}); // how do I convert it here to file descriptor - if even possible
console.log(newsock);
});
});
server.listen(socket, function() {
console.log('server bound');
});
client side:
var net = require('net');
var socket = '/host/testing.node.sock';
var fs = require('fs');
client = net.connect({path: socket}, function () {
// here we create a new server that we want the fd passed to other server
var newSock = '/tmp/testing.node.sock';
if (fs.existsSync(newSock)) {
fs.unlinkSync(newSock);
}
// create a new server
var server = net.createServer(function (c) { //'connection' listener
console.log('server connected');
c.on('end', function () {
console.log('server disconnected');
});
c.on('error', function (e) {
console.log(e);
});
c.on('data', function (data) {
console.log("data received");
console.log(data);
});
});
server.listen(newSock, function () { //'listening' listener
console.log('server bound');
console.log(server);
// here we want to pass the new fd
client.write(new Buffer(server._handle.fd));
});
});
Thanks
Back in node v0.4 this functionality existed for both sending and receiving but it was later removed. You'll have to write your own binding to allow you to send/receive file descriptors on an existing fd (your unix domain socket, whose fd should be accessible in node IIRC). Here are some links to get you started.
As described in https://github.com/nodejs/help/issues/345,
Node doesn't support this anymore because there's no way to do it on Windows. But this package provides a UNIX socket API that can send file descriptors: https://www.npmjs.com/package/usocket

Resources