Page doesn't automatically update when socket.io receive - javascript

I want to page update when new socket.io data appear.
I have a server -> client comunication:
Server code (the n var is the message)
io2.on('connection', function(socket2) {
socket2.on('live', function(data2) {
console.log('status from live client:', data2);
socket2.emit('live', n);
});
});
Live page code:
var socket = io.connect('http://localhost:3002');
socket.emit('live', 'live client is connected');
socket.on('live', function(data) {
//alert(data)
document.getElementById("demo").innerHTML = data;
});
The socket works fine because when I send the data and I refresh the page it show what I want. The problem is that I want to see the updated message without manual refresh.
Thanks!

The scope for n is undefined in the first function, so the receiving function doesn't have anything to show.
You'll need to define n in the original emitting function.

You need to emit the event from server side to the client side and then catch data there
var server = app.listen(3000);
var io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.on('event', function(data) {
var n = data.message;
io.sockets.emit('event', message);
});
And then on frontend in live page you write this
var n = <%-JSON.stringify(v1)%>;
var socket = io.connect('http://localhost:3000');
socket.on('event', (data)=>{
console.log(data)
});

Related

Using Socket.IO from Node.js to connect to external server

Background: I have a node.js server running on my localhost (call this Server A); and an external server running node.js at https://example.net:3000 (call this Server B). I do not control or have access to Server B (it is a dashboard site for an IoT device in my home), but I need to connect to is using socket.io and emit a specific message.
I can connect to it easily from a flat javascript file (client-side), but need it running server side (ultimate goal is to make it into something I can call with an HTTP request); and examples such as How to connect two node.js servers with websockets? suggest I should be able to use socket.io-client from node.js with nearly the same code to achieve the same results. But when I run the code from node.js, I cannot connect to the socket.
Below is the code that works successfully in flat javascript file. I know it works because I see 'socket connect' in the console, and I can also test for the the socket emit at the end.
var myemail = "email#gmail.com";
var device_id = '12345';
// Create SocketIO instance, connect
var socket = io.connect('https://example.net:3000');
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
...and below is the code I cannot get to work when running from my node.js instance. I'd expect a message 'socket connect' in the command line log and get nothing.
var express=require('express');
var http=require('http');
var app=express();
var server = http.createServer(app);
//Variables
var myemail = "email#gmail.com";
var device_id = '12345';
var io = require('socket.io-client');
var socket = io.connect('https://example.net:3000');
//Connect listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
Any ideas?
UPDATE
Ran debug utility, results included as linked image below. Key thing I see is that engine.io tries to do an xhr poll, and gets a 503 response back from the server. (Obviously not a true 'temporary error' with the server as again, this all works from running client-side js in chrome).
debugging output image link
Solved this - issue was that the server I was connecting to required use of https, so I needed to add
{secure: true, rejectUnauthorized: false}
after the url to connect to.
Full working example:
const myemail = email#email.com;
const device_id = 12345;
io = require('socket.io-client');
var socket = io.connect('https://server.net:3000',{secure: true, rejectUnauthorized: false});
function doStuff(){
//Listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "003021");
}
doStuff();
I think the line causing the issue is :
var socket = io.connect('https://example.net:3000');
I managed to make a working example using this code :
const myemail = "email#gmail.com";
const device_id = '12345';
var socket = require('socket.io-client')('https://example.net:3000');
socket.on('connect', function(){
try{
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
}catch(e){ console.log(e); }
});

How to push notification to specific user Node + AngularJS + Laravel

I need help how to push notification to specific user. I can now push notifcation but all user will get that notification. I can filter it on clinet side but I think it is unsecure...
First I send data with laravel 5:
$redis = Redis::connection();
$redis->publish('update.answer', json_encode($events));
here is my node.js i emite data:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('update.group', function(err, count) {
});
redis.subscribe('update.question', function(err, count) {
});
redis.subscribe('update.answer', function(err, count) {
});
redis.subscribe('update.comment', function(err, count) {
});
redis.on('message', function(channel, message) {
message = JSON.parse(message);
console.log(message);
io.emit(channel, message);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
and with angularjs I take data and push to the client.
socket.on('update.answer',function(data){
if($scope.remove){
$scope.remove = false;
}
$scope.feed = $("#feed").val();
if(parseInt($scope.feed) === parseInt(data.userID)){
$scope.answers.push(data);
$scope.$digest();
}
});
WIth this part:
$scope.feed = $("#feed").val();
if(parseInt($scope.feed) === parseInt(data.user_id) && data.admin_id !== null){
}
I check if client should get notification but it is unsecure...
Any way to improve this?
To push message to specific user , you must store his/her reference somewhere.
for ex
io.on('connection', function(socket) {
socket.on('add-user', function(data){
clients[data.username] = socket;
});
});
now to push message to specific user just use his username to retrive his socket
clients[data.username].emit(channel, message);
Update : Explanation
This Assume that each user who uses you web app is having some sort of authentication.
As soon as user login into your application , let him join on the nodejs backend socket.
on client side
socket.emit('add-user',userObj);
});
userObj is object that contains user details,you can send the username alone too
socket.emit('add-user',username);
in your nodejs first decalre one array that contains the socket of all the users who joins the website
var clients = [];
now in your nodejs application write this additional code
io.on('connection', function(socket) {
socket.on('add-user', function(data){
clients[data.username] = socket;
});
});
up to this moment the user who login into your website will call add-user event from client side which will in turn call add-user on nodejs and there socket will be added into the clients array
now to send message to any particular user you must know there username,so if you know the username of the user then you can simply emit message to them using
clients[data.username].emit(channel, message);

User receive more than 1 notification from nodejs

This is my first time with nodejs and I have some issues with it. The main problem is that the user receive more than 1 signal from the server. The count is based on the refresh of the page.
Below is my code:
var http = require('http');
var server = http.createServer().listen(1332);
var io = require('socket.io').listen(server);
var redis = require('redis');
var sub = redis.createClient();
//Subscribe to the Redis chat channel
sub.subscribe('notification_count');
console.log("Server is running...\nClick on Ctrl+C to exit");
io.sockets.on('connection', function (socket) {
var user_id = socket["handshake"]["query"]["user_id"];
console.log("user_id", user_id);
socket.room = user_id;
socket.join(user_id);
socket.on('disconnect', function(){
socket.leave(socket.room);
});
//Grab message from Redis and send to client
sub.on('message', function(channel, message){
io.sockets.in(message).emit('message', message );
});
});
And here is the client side js code:
var socket = io.connect('localhost:1332', { query: "user_id={{ request.user.id }}" });
socket.on('connect', function(){
console.log("connected");
});
socket.on('message', function(message) {
//something
});
Basically on connection from the server I send to the server the user_id. After that I create a new room which name is the same as the user_id. Of course on disconnect the room should be delete. I have noticed that sub.on() is fired more than once, but I cannot figure out why. I will appreciate any help. Thank you in advance !
The problem is that you are using a handler inside the connection event, everytime a client connects it will execute everything inside the connection event including your sub.on
Place sub.on out of the connection event and it should stop the double messages

calling a socket inside another socket using node.js and socket.io

I am a trying to use socket.io and node.js like this :
The browser sends an event to socket.io, in the data event I call another server to get some data, and I would like to send back a message to the browser using a socket.emit.
This looks like that :
socket.on('ask:refresh', function (socket) {
const net = require("net");
var response = new net.Socket();
response.setTimeout(1000);
response.get_response = function (command, port, host) {
this.connect(port, host, function () {
console.log("Client: Connected to server");
});
this.write(JSON.stringify({ "command": command }))
console.log("Data to server: %s", command);
};
response.on("data", function (data) {
var ret = data.toString();
var tmp_data = JSON.parse(ret.substring(0, ret.length - 1).toString());
var data = new Object();
var date = new Date(tmp_data.STATUS[0].When * 1000 );
data.date = date.toString();
socket.emit('send:refresh', JSON.stringify(data) );
});
response.get_response("version", port, host);
});
};
The thing is that I cannot access "socket.emit" inside response.on.
Could you please explain me how I can put a hand on this ?
Thanks a lot
You appear to be overwriting the actual socket with the one of the callback parameters:
socket.on('ask:refresh', function(socket) {
// socket is different
});
Change the name of your callback variable, and you won't have this problem.

how to get session id of socket.io client in Client

I want to get session id of client in my socket.io client.
here is my socket.io client :
var socket = new io.Socket(config.host, {port: config.port, rememberTransport: false});
// when connected, clear out display
socket.on('connect',function() {
console.log('dummy user connected');
});
socket.on('disconnect',function() {
console.log('disconnected');
});
socket.connect();
return socket;
I want to get session id of this client , how can i get that ?
Have a look at my primer on exactly this topic.
UPDATE:
var sio = require('socket.io'),
app = require('express').createServer();
app.listen(8080);
sio = sio.listen(app);
sio.on('connection', function (client) {
console.log('client connected');
// send the clients id to the client itself.
client.send(client.id);
client.on('disconnect', function () {
console.log('client disconnected');
});
});
On socket.io >=1.0, after the connect event has triggered:
var socket = io('localhost');
var id = socket.io.engine.id
I just had the same problem/question and solved it like this (only client code):
var io = io.connect('localhost');
io.on('connect', function () {
console.log(this.socket.sessionid);
});
* Please Note: as of v0.9 the set and get API has been deprecated *
The following code should only be used for version socket.io < 0.9
See: http://socket.io/docs/migrating-from-0-9/
It can be done through the handshake/authorization mechanism.
var cookie = require('cookie');
io.set('authorization', function (data, accept) {
// check if there's a cookie header
if (data.headers.cookie) {
// if there is, parse the cookie
data.cookie = cookie.parse(data.headers.cookie);
// note that you will need to use the same key to grad the
// session id, as you specified in the Express setup.
data.sessionID = data.cookie['express.sid'];
} else {
// if there isn't, turn down the connection with a message
// and leave the function.
return accept('No cookie transmitted.', false);
}
// accept the incoming connection
accept(null, true);
});
All the attributes, that are assigned to the data object are now accessible through the handshake attribute of the socket.io connection object.
io.sockets.on('connection', function (socket) {
console.log('sessionID ' + socket.handshake.sessionID);
});
On Server side
io.on('connection', socket => {
console.log(socket.id)
})
On Client side
import io from 'socket.io-client';
socket = io.connect('http://localhost:5000');
socket.on('connect', () => {
console.log(socket.id, socket.io.engine.id, socket.json.id)
})
If socket.id, doesn't work, make sure you call it in on('connect') or after the connection.
For some reason
socket.on('connect', function() {
console.log(socket.io.engine.id);
});
did not work for me. However
socket.on('connect', function() {
console.log(io().id);
});
did work for me. Hopefully this is helpful for people who also had issues with getting the id. I use Socket IO >= 1.0, by the way.
Try from your code
socket.socket.sessionid
ie.
var socket = io.connect('http://localhost');
alert(socket.socket.sessionid);
var sendBtn= document.getElementById('btnSend');
sendBtn.onclick= function(){
var userId=document.getElementById('txt1').value;
var userMsg = document.getElementById('txt2').value;
socket.emit('sendto',{username: userId, message: userMsg});
};
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
socket.on('message',function(data){ console.log(data);});
Try this way.
var socket = io.connect('http://...');
console.log(socket.Socket.sessionid);

Categories