I have several client connections and one should listen for data in other. How can I make a bridge between them (not an array iterator)?
Sample pseudo-code:
socket.on('data', function(chunk){
decodeChunk(chunk.toString('hex'), function(response){
if(response.name === 'toDB'){
//write smth. to DB
}
if(response.name === 'readDB'){
//watch all incoming tcp sockets with 'toDB' and continiously
//send to client connected with this socket
}
});
})
I can use something like rabbitMQ, but it's not for current stage in order to keep development more agile.
Any suggestions appreciated.
It's a bit tricky to address this with purely pseudo code, but I ll give it a shot anyway.
If I understand this correctly, then toDB and readDB are sample data and there are multiple toDB. Which means, you'd also have a bunch of toXY with a corresponding readXY OR a bunch of toPQ with corresponding readPQ. If so, then as soon as a toSOMETHING is connected, you can store that socket under a readSOMETHING. If the key already exists, then you d simply append the toSOMETHING socket to it. In time it would look something like this:
var socketData = {
readDB: {
sockets: [
<socket-object-toDB-1>,
<socket-object-toDB-2>,
<socket-object-toDB-3>
]
},
readXY: {
sockets: [
<socket-object-toXY-1>,
<socket-object-toXY-2>,
<socket-object-toXY-3>
]
}
}
And then your pseudo code would probably look something like
socket.on('data', function(chunk){
decodeChunk(chunk.toString('hex'), function(response){
if(response.name === 'toDB'){
//write smth. to DB
if (socketData['readDB']) {
// already exists, simply append incoming socket to it's sockets array
socketData['readDB'].sockets.push(socket);
} else {
// does not exist, add it with a sockets array
socketData['readDB'] = {
sockets: [socket]
}
}
if(response.name === 'readDB'){
// Write to all sockets of readDB
socketData['readDB'].sockets.forEach(function(sock) {
sock.write('Whatever message\r\n');
});
}
});
})
Ended up with such service:
var SocketMedium = {
sessions: {},
onEvent: function (event, cb) {
if (!this.sessions[event]) {
this.sessions[event] = [];
this.sessions[event].push(cb);
} else {
this.sessions[event].push(cb);
}
console.log('onEvent: ', event);
},
rTrigger: function (event, data) {
console.log('Started rTrigger: ', event);
if(this.sessions[event]){
console.log('FOUND: ', event);
this
.sessions[event]
.forEach(function (cb) {
cb(data);
})
}
console.log('Completed rTrigger', this.sessions);
},
cleaner: function(sessionId){
var event = 'session' + sessionId;
if (this.sessions[event]) {
delete this.sessions[event];
console.log('SocketMedium cleaned: ', this.sessions[event]);
}
console.log('SocketMedium can not find: ', this.sessions[event]);
}
};
module.exports = SocketMedium;
Related
I'm using NodeJS and Socket.io. I'm getting a query from the user (https://localhost:3000?id=12345) and using this query I want to send this specific user unique content.
Now my problem is that all clients are getting data according to the last query from the last client.
I've tried to make rooms and multiple other solutions that I've thought about or found online but with no luck.
I'm getting the query of the page like that,
app.get('/', async ({ query }, response) => { ... }
Client
$(document).ready(function () {
socket.emit('room', key);
socket.on('a1', function (data) {
$("#a1").empty().append(data);
});
socket.on('a2', function (data) {
$("#a2").empty().append(data);
});
socket.on('a3', function (data) {
$("#a3").empty().append(data);
});
socket.on('a4', function (data) {
$("#a4").empty().append(data);
});
…
Server
io.on('connection', function (socket) {
console.log('Connection');
socket.removeAllListeners();
socket.on('create', function (data) {
console.log(`Data: ${data}`);
socket.join(data);
io.in(data).emit('a1', a1);
io.in(data).emit('a2', a2);
io.in(data).emit('a3', a3);
io.in(data).emit('a4', a4);
})
});
…
I really can't understand how to separate each client query from the server and then send unique content to each client without one client's content interfering with another.
My initial thought was to make one room per client and send their unique content by using that room but for some reason, it's like the content is ending up in every client.
Thank you very much!
Is just you turn the object used to manage the content better like this:
The clientside:
$(document).ready(function () {
const userKey = 'unique-id-for-each-user'
socket.emit('room', {key : key, userKey : userKey});
//if you emit something in this channel (same as userKey) on server will get here
socket.on(userKey, function (data) {
if(data.key === 'a1')
$("#a1").empty().append(data.content);
if(data.key === 'a2')
$("#a2").empty().append(data.content);
if(data.key === 'a3')
$("#a3").empty().append(data.content);
});
//if you emit something in this channel ('allClients') on server will get here
socket.on('allClients', function(data) {
if(data.key === 'a1')
$("#a1").empty().append(data.content);
if(data.key === 'a2')
$("#a2").empty().append(data.content);
if(data.key === 'a3')
$("#a3").empty().append(data.content);
})
});
The serverside:
io.on('connection', function (socket) {
console.log('Connection');
socket.removeAllListeners();
socket.on('room', function (data) {
console.log(`Data: ${data}`);
if(data.key === 'a1')
io.sockets.emit(data.userKey, {key : 'a1', content: a1});
if(data.key === 'a2')
io.sockets.emit(data.userKey, {key : 'a2', content: a2});
if(data.key === 'a3')
io.sockets.emit(data.userKey, {key : 'a3', content: a3});
if(data.key === 'a4')
io.sockets.emit(data.userKey, {key : 'a4', content: a4});
})
});
As you see, i just change the variable you pass as parameter to give me what i need, as serverside as clientside.
I am using react-native with socket.io to send and receive contact requests but my code is only emitting to the emitter and to no one else.
This is the server side:
users = []; // Each time a new user joins the server they are saved in this array
socket.on('create connection', function(data, callback) {
if(data.receiverId in users) { // If the user you want to add is online then callback is true else callback is false
// The underneath line is the one that I will be using but nothing happend
//io.sockets.in(data.receiverId).emit('save room', data);
// So I created this one to see if I actually was emitting something
socket.emit('save room', data); // I found out that the emitting was working but only with the emitter
callback(true);
}else
callback(false);
});
So my conclusion is that my server side is correct and the problem lies on my client side
This is my client side:
constructor() {
this.socket = SocketIOClient('http://192.168.15.4:8000');
this.socket.on('save room', function (data) { // This is where the server calls the emit. It was at first inside the connect function but I moved it to the constructor to see if that way all clients could get it, results are the same
Alert.alert(
'Accept Connection?',
'User: '+data.emitterId+' sent you a connection request',
[
{
text: 'Accept',
onPress: () => {},
},
{
text: 'Refuse',
onPress: () => {},
},
],
{cancellable: false}
);
})
}
#action connect(data, callback1) { // this access the function we had previously in the server
this.socket.emit('create connection', data, function (callback2) {
if(!callback2)
Alert.alert(
'User Offline',
'This user is currently offline try again later',
[
{
text: 'OK',
onPress: () => {callback1(false)},
},
],
{cancellable: false}
);
else {
callback1(true)
}
});
}
I think the problem lies on where I place the this.socket.on('save room') function, but in react-native I really do not know where to put it.
Thanks to #H. Tugkan kibar and #azium I realized that the problem was on my server side the correct way to emit to a specific user is like this:
socket.broadcast.to().emit();
I'm really confused at this point with losing data and can't figure out why. So I write a service to send GPS info from a device to an endpoint.
I'm using pm2 to launch my processes but the problem is this service sometimes don't send the info to the endpoint, and the device is sending data. The solution until now was restarting the instance in pm2. But this sometimes is not viable because I create a crontab to restart the GPS instance in pm2 every 45 minutes but it happens to lose information in a time window < 45 min this will not work...
I can't figure this out. Why I lose the data and restarting everything is okay? I saw a post in stack overflow about lost data in node.js process when the child sends the data to the parent and I read about 2 possible causes:
The child is not reading the GPS data info quickly enough in time to make a post and send info.
The child needs to make a JSON.stringify of the content sent to parent and parent needs to make a JSON.parse of the info received.
Here's my code:
var child_process = require("child_process");
var argv = require('minimist')(process.argv.slice(2));
//ex: nsGPSService.js -d 1111-11-11-111
var deviceId = argv.d;
var processDevices = [];
function runParent() {
setTimeout(function() {
return Database.Devices.getDevices().then(function(devices) {
return new Promise(function(resolve, reject) {
async.each(devices, function(device, callback) {
var result = _.filter(processDevices, { "id": device.id });
if (result.length == 0) {
var process = child_process.fork(__dirname + '/nsGPSService.js', ["-d", device.id]);
processDevices.push({ "process": process, "id": device.id });
process.on('message', function(data) {
//receber mensagens do filho
if (data.reason == "deleted") {
//child end process and alerts parent to remove from the list
var index = _.findIndex(processDevices, { "id": data.deviceId });
processDevices.splice(index, 1);
}
});
process.on('exit', function(code) {});
process.on("uncaughtException", function(error) {
process.exit(1);
});
}
callback();
}, function(error) {
error ? reject(error) : resolve();
});
}).then(function() {
runParent()
}).catch(function(error) {
runParent()
});
});
}, 5000);
}
if (!deviceId) {
return runParent();
}
function runChild(id) {
setTimeout(function() {
return Database.Devices.getDeviceById(id).then(function(device) {
if (!device) {
proccess.send({
"deviceId": id,
"reason": "deleted"
});
process.exit();
return;
}
return Controllers.Gps.getRadioInfo('gps', 'info', {}, device).then(function(data) {
return Controllers.Gps.sendDeviceInfo(data, device);
}).then(function() {
return runChild(id);
}).catch(function(e) {
return runChild(id);
});
});
}, 5000);
}
I really need to figure this out because I never know when I need to restart the service because I'm not getting info when in reality I'm receiving...
Which solution is really viable in my scenario and anyone can figure this problem?
I am working in UI automation testing project i need to send a ajax request to my server but in Nighwatch.js some functions of vanilla javascript and JQuery functions are not acceptable,
so if anyone has any experience to send Ajax get request to server in nightwatch.js environment then please give me some info/suggestions.
After long research i found request.js a node module, I have resolved my issue by installing "request" node module. After installing i am able to perform "GET" and "POST" requests to my servers within Nightwatch environment. I am writing piece of code which working like a charm.
/* jshint expr: true */
module.exports = {
'#tags' : ['book'],
beforeEach : function (client) {
},
after : function (client) {
client.end();
},
wGroup: {
book_url: "https://example.myApi.mycompany.in"
},
userSettings: Array(),
"Get all settings": function (client, done) {
var widget = this.wGroup;
client.getreq( widget.book_url + "/api/store", widget, function (response) {
client.assert.equal(response.statusCode, 200, "201 Created");
var objects = response.body.objects;
client.userSettings = objects;
console.log( 'Found number of settings: ' + client.userSettings.length );
client.end();
});
},
"Remove settings": function (client, done) {
var widget = this.wGroup;
var objects = client.userSettings;
for( i=0; i<objects.length; i++ ) {
var obj = objects[i];
console.log('Removing user settings id ' + obj.id );
client.deletereq( widget.book_url: l + "/api/store" + obj.id, widget, function (resp) {
client.assert.equal(resp.statusCode, 204, "204 Created");
client.end();
});
}
},
};
Hei,
Im stuck for some reason. Im playing around with Arduino board and I want to read the data in the client.
My server code is this:
if(Meteor.isServer) {
var five = Meteor.npmRequire("johnny-five");
var board = new five.Board();
Meteor.startup(function() {
board.on("ready", Meteor.bindEnvironment(function() {
var temperature = new five.Thermometer({
controller: 'TMP36',
pin: 'A0'
});
Meteor.setInterval(function() {
console.log(temperature.celsius);
}, 5000);
}))
})
}
I don't want to save the data to collection but to read it online. How do I pass the variable temperature.celsius from server to the client? I cannot run the code in the client since i'm using NPM require and it works only in the server.
Right after the Meteor.setInterval definition, add this:
Meteor.methods({
temperature: function () {
return temperature;
},
});
Then add, at the bottom of your code:
if (Meteor.isClient) {
Template.tempReport.result = function () {
return Session.get('temperature') || "";
};
Template.tempReport.events = {
'click button' : function () {
Meteor.call('temperature',function(err, response) {
Session.set('temperature', response);
});
}
};
}
And finally in your HTML:
<template name="tempReport">
<div>Temperature: {{temperature}} <button>Update</button></div>
</Template>