Get remote endpoint properties on node.js socket close/end events - sockets

I have a node.js server which keeps track of all "clients" connected to it, using an associative array of sockets, because I need to send some data to specific clients sometimes. The keys in that array are strings composed of
socket.remoteAddress + ':' + socket.remotePort
and values are socket instances passed to the callback provided to net.createServer(...)
Sometimes the clients disconnect for one reason or another and I receive the 'end' and then 'close' events. I'd like to remove the disconnected clients from my client registry but in the close/end event callbacks, the remoteAddress and remotePort variables are undefined. Can they be retrieved somehow?
To illustrate:
var registry = {}
var server = net.createServer(function (socket) {
socket.on('connect', function(){
registry [socket.remoteAddress + ':' + socket.remotePort] = socket;
});
socket.on('close', function(had_error){
// ******************************************************
// socket.remoteAddress and remotePort are undefined here
// ******************************************************
var id = socket.remoteAddress + ':' + socket.remotePort;
// *************************************************************
if(registry.hasOwnProperty(id)
delete socket.id;
});
});

I think you should use socket.id instead of creating your own object property that might not be unique
socket.on('connect', function(){
registry [socket.id] = socket;
});
UPDATE
Node provides basic http API. Http is stateless. HTTP sessions allow associating information with individual visitors but node doesn't have a native sessions support.
Take a look at express, it is a nice web framework with sessions support
Also, if you need to send messages in a realtime fashion, take a look at socket.io
UPDATE V2
You can add your own ID property to the socket object:
function randomID(len){
//Generate a random String
return randID;
}
var registry = {}
var server = net.createServer(function (socket) {
socket.on('connect', function(){
var uid = randomID(32);
socket.id = uid;
registry [uid] = socket;
});
socket.on('close', function(had_error){
var uid = socket.id;
// *************************************************************
console.log("Socket ID " + uid + " disconnected")
});
});

Related

Socket programming in yii2 to provide web service support to the mobile app

I have a requirement to provide the real time data to the mobile app through web services. I have developed the project in yii2 and want to implement socket programming so that i could connect the mobile app and can send the updated real time data to the app.
For Details :
We have to provide the live tracking feature to our mobile app user.
For that we are storing the mobile app user's current location(Lat/long) and storing it on server. When any user want to track his friend(Which is the user of our app) location he can, for which we have to keep sending his friend's current location to the app so that he can see him moving on map when he is roaming anywhere.
I have google for the socket programming with Yii2 but every where i am getting the example for chat functionality through sockets.
Can any body help who has worked something matching with my requirements.
Socket programming to send data from server to mobile app client.
Thanks in advance.
Finally, After putting so much efforts and spent a week of time on R&D i just got what i was require.
Here i am posting the solution which i have developed for my requirements considering for those who have the similar requirements, may be it could help full for them :
Server.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var clientsids = {};
var response_array = get_response_array();
server.listen(8786);
io.on('connection', async function (socket) {
var uchannel = socket.handshake['query']['r_var'];
var myid = socket.handshake['query']['myid'];
clientsids[uchannel+'_'+myid] = socket.id;
socket.join(uchannel);
socket.emit('connectSuccess',response_array);
//sending current data to the user
socket.on('currentlocation', function(data) {
console.log("User with id :"+data.myid+ " has shared the location : lat :"+data.lat+",lng :"+data.lng+" in channel :"+data.channel);
//dump user location to a file for future save to the db
fileobj.savelocation(data.myid,data.lat,data.lng);
response_array = get_response_array();
response_array['msg_code'] = 103;
response_array['msg'] = get_msg_code(103);
var datainfo = {};
datainfo['lat'] = data.lat;
datainfo['lng'] = data.lng;
datainfo['channel_name'] = data.channel;
datainfo['u_id'] = data.myid;
response_array['data'] = datainfo;
fileobj.dumpdata("User with id :"+data.myid+" has shared the location : lat :"+data.lat+",lng :"+data.lng+" in channel :"+data.channel+" \n"+JSON.stringify(response_array));
io.to(data.channel).emit(data.channel, response_array); //broadcast the data to all the users in the channel
//console.log('current clients :'+ JSON.parse(clientsids));
});
socket.on('disconnect', function() {
//redisClient.quit();
socket.disconnect('disconnect');
});
});
Client.php
var room ='';
var myid ='';
var socket ='';
$( document ).ready(function() {
room = $("#channel").val();
room2 = $("#channel2").val();
myid = $("#myid").val();
socket = io.connect('serverip:port',{
query: 'r_var='+room+'&myid='+myid
});
socket.on(room, function (data) {
$( "#notifications" ).prepend( "<p><strong>Message :" + data.msg + " </strong> <strong>Channel :" + data.data.channel_name + "</strong> <strong>Lat :" + data.data.lat + "</strong> <strong>Long :" + data.data.lng + "</strong></p>" );
});
socket.on('connectSuccess', function (data) {
$( "#notifications" ).prepend( "<p><strong>" +data.msg+ "</strong>: ");
});
});

How to get JID, SID and RID from actual version of Smack

I have the following problem:
How can i get these three (JID, SID and RID) parameters after a successful connection to an openfire server?? with Babbler it is relative easy to get them, but with Smack is kinda of difficult, when not impossible, to find it.
Best Regards.
You may find what you need by this link:
Java - trying to prebind converse.js using bosh but not able to get the sid and rid...using the smack bosh
Other way, if you can use javascript to get jid, sid and rid, you can refer below:
You can use strophe.js to create a bosh bind first, then get them from the connection.
//I user local openfire here
var BOSH_SERVICE = 'http://127.0.0.1:7070/http-bind/';
var connection = null;
//you can get your usr and pwd in other way
var jid = 'admin#127.0.0.1';
var password = 'admin';
connection = new Strophe.Connection(BOSH_SERVICE);
connection.connect(jid,
password,
onConnect);
and then get the detail from onConnect() function like this:
function onConnect(status)
{
if (status == Strophe.Status.CONNECTED) {
//then you can get what you want
console.log("---SID[" + connection._proto.sid + "] RID[" + connection._proto.rid + "] JID[" + jid + "]");
}
}
good luck!

How to send message to individual client in node.js using only Net module(not socket.io)

Simple code:
process.stdin.resume()
process.stdin.setEncoding('utf8');
var server = createServer();
server.listen(9999);
server.on('connection',function(sock){
console.log('CONNECTED:'+sock.remoteAddress+":"+sock.remotePort);
process.stdin.on('data',function(send){
sock.write(send);
});
}
When receiving connection from 10.10.10.1 and 10.10.10.2,
message "CONNECTED:10.10.10.1:xxx" and "CONNECTED:10.10.10.2:xxx"
are display on terminal
To send message to a client, I used sock.write(send)..
but, All clients received message
How can I send a message to a specific client.
From googling there are many socket.io related documents(solutions)..
but, before using socket.io, I want to know node.js itself.
(or javascript itself?)
After reading Vadim's comment, I wrote down more code below.
fully working code.
I add two things. According to Vadim's comment, add property sock.id
and using property sock.remoteAddress, send server's stdin message to
10.10.10.1 client only
var net = require('net')
process.stdin.resume()
process.stdin.setEncoding('utf8');
var server = net.createServer();
server.listen(9999);
server.on('connection',function(sock){
sock.write('input your ID: ',function(){
var setsockid = function(data){
id=data.toString().replace('\r\n','');
console.log('ID:'+id+' added!!')
sock.id=id
sock.removeListener('data',setsockid);
};
sock.on('data',setsockid);
sock.on('data',function(data){
d=data.toString().replace('\r\n','');
console.log(sock.id+' say: '+d);
});
});
console.log('CONNECTED:'+sock.remoteAddress+":"+sock.remotePort);
process.stdin.on('data',function(send){
if (sock.remoteAddress=='10.10.10.1') sock.write(send);
});
});
Answer to your question is on Node.JS main page.
var net = require('net');
var server = net.createServer(function (socket) {
socket.write('Echo server\r\n');
socket.pipe(socket);
});
server.listen(1337, '127.0.0.1');

Socket.io Client Request Origin URL

On the client, in the browser, I have this code:
this.socket.on('initial', function(data) {
console.log(data);
});
On the server I have:
socket.sockets.on('connection', function(client){
console.log('client connected');
});
My question is: how can I detect the URL where the request came from? For example if the first closure was running on "/posts/view/1", I want to be able to detect it inside of the second closure.
You could send this data back to the server. A little hand-wavey on the details, but how about something like:
On the client:
this.socket.on('initial', function(data) {
// do whatever with data
var my_location = get_page_location_with_javascript(); // or whatever
this.socket.emit('phone_home', my_location);
});
On the server:
this.sockets.on('phone_home', function(url) {
console.log("The URL was " + url);
});

Communication between several node.js process

I have 3 node.js application (A, B, C). A is an entry point and I like all the request that gets to this entry point to be redirected toward B or C (depending upon the value of a parameter in the request).
Currently I'm doing so with a res.redirect in A (I'm using expressjs framework). That's working fine except that it's not really transparent (I can see from the outside that the original request has been redirected).
To solve this, I will have B and C listen on socket instead of port number but I do not know how to have A redirecting the request to the sockets used by B or C.
Any idea on how to have 2 node.js process communicating via sockets ?
** UPDATE **
I have changed the code of A to use node-proxy:
app.all('/port/path/*', function(req, res){
// Host to proxied to
var host = 'localhost';
// Retrieve port and build new URL
var arr_url = req.url.split('/');
var port = arr_url[1];
var new_url = '/' + arr_url.slice(2).join('/');
console.log("CURRENT URL:" + req.url); // url is /5000/test/...
console.log("NEW URL :" + new_url); // url is /test/...
// Change URL
req.url = new_url;
var proxy = new httpProxy.HttpProxy();
proxy.proxyRequest(req, res, {
host: host,
port: port,
enableXForwarded: false,
buffer: proxy.buffer(req)
});
console.log("Proxied to " + host + ':' + port + new_url);
// For example: the url is localhost:10000/5000/test
// the log tells me 'Proxied to localhost:5000/test' => that is correct
// But... I do not get any return
// If I issue 'curl -XGET http://localhost:5000/test' I get the return I expect
});
Any obvious mistake in this ?
You're on the right track with having the other processes listen on different ports. What you're talking about is called a reverse proxy. If its http, its pretty straightforward to get this going with node-http-proxy:
https://github.com/nodejitsu/node-http-proxy
You want to set something up like a proxy table:
var options = {
router: {
'foo.com/baz': '127.0.0.1:8001',
'foo.com/buz': '127.0.0.1:8002',
'bar.com/buz': '127.0.0.1:8003'
}
};
I just put in an issue for for the node-http-rpoxy module here https://github.com/nodejitsu/node-http-proxy/issues/104
Apparently it does in fact work with unix sockets right now, but like this (subject to change).
var options = {
router: {
'foo.com/baz': ':/tmp/nodeserver.sock',
}
};
All it needs is a colon to use the socket path as the port value.