Nodejs - socketio - update info in all browser windows - javascript

I just started up learning how to make web applications. I am making a webserver in nodejs (a to-do list app). I am using the express framework, and mongodb as database. For communication between the client and the server i am using socket.io.
I can't find a way to make it so that when the server emits and event the client will update the info on all of his open windows of the page. Right now the info updates only on the window that triggered the event on ther server. This is the server code:
Server code:
var io = require('socket.io').listen(server);
io.of('/home').on('connection', function (socket) {
socket.on('newListGroup', function (data) {
...
socket.emit('groupNo', obj);
});
}); `
Client javascript:
var socket = io.connect('http://localhost/login');
socke.on('groupNo', function(data){ ... });
$('#newListGroup').blur(function() {
socketLogin.emit('newListGroup', {newGroup:newGroup});
});
Can this work or should I take another approach?

You can broadcast a message to all sockets like this:
var io = require('socket.io').listen(server);
io.of('/home').on('connection', function (socket) {
socket.on('newListGroup', function (data) {
socket.broadcast.emit('groupNo', obj); });
});
It should be limited to the namespace but you will probably have to implement your own logic for broadcasting only to windows on the same client (probably using authentication) if that is what you want to do.

Related

How to use socket.io to display realtime data in the client (web browser) from the node.js server?

I want to display the real-time speech to text data in the browser. By real-time what I mean is, "while I am speaking I am getting the text output simultaneously". I have implemented the speech-to-text part in Python using the Google cloud service API. Then I used "child process" to run my python program in the node.js environment. Till now everything is fine. Next, I want to display the real-time text in the browser. In another word, I want to send the real-time text output from the python (which is now running in node.js using the child process) to the web browser. I was trying to do that with socket.io. Here is my server side (node.js) code where socket.io is also applied:
const express = require('express');
//const router = express.Router();
const {spawn} = require('child_process');
const path = require('path');
const app = express();
const http = require('http');
const server = http.createServer(app);
//const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
function runScript(){
return spawn('python3', [
"-u",
path.join(__dirname, 'script.py')
]);
}
const subprocess = runScript()
// print output of the script
app.get('/', (req,res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
Above, I am first using the child process to call the python program in node.js and then I am using socket.broadcast.emit to send the text output of the python program to my client side. The client-side code looks like this:
<!DOCTYPE html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages');
//const EventEmitter = require('events');
//const emitter = new EventEmitter()
//emitter.setMaxListeners(50)
socket.on('messages', function(data) {
document.querySelector("#style1".innerHTML = `<p>${data1}</p>`
});
</script>
</head>
<body id="messages">
<h1> This is crazy </h1>
<div id="style1">
</div>
</body>
</html>
Above, I want to display the real-time text output from the python program inside the <p> tag.
The problem is, I am not able to get anything in the web browser.
My objective is, I want to display whatever I am speaking as text in the web browser in real-time.
I don't know much about socket.io. In fact, this is the first time I am using this technology.
Your Node.js server will act as the socket server. As your code shows, it listens on a port for a socket connection, and on connection, creates a socket, which you then send messages too. From a simple cursory review, the server code looks okay.
On your webpage, you are creating the socket, and listening for messages.
However the socket running on the webpage hasn't yet connected to the server, which is why nothing is working yet.
Assuming you're doing this on localhost, just add the socket server address to it's constructor, and then listen for connect.
const socket = io('ws://localhost:3000');
socket.on('connect', () => {
// do any authentication or handshaking here.
console.log('socket connected');
});
More advanced implementations should gracefully handle closing sockets.
Per the following comment:
I added the lines you suggested above. Even now nothing is visible on the webpage but I am getting this warning: (node:14016) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message listeners added. Use emitter.setMaxListeners() to increase limit
Looking more closely at your server code, I believe this is the root issue
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
Each time you receive data from subprocess.stdout, you are adding a new onmessage event handler to your socket, so after a period of time, you have added too many event handlers.
Re-write your logic so that you only add socket.on('message') once (usually after your create the socket).
It is also worth noting that in the above code, data from stdout is not being used, as that data variable is being redefined in a lower scope by your onmessage function. Since data is being redefined, the output of your Python program is being ignored.
I think this is what you want:
//echo any message you receive from the socket back to the socket
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
//send data from std out to the socket.
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.broadcast.emit('message', data);
});

How to Callback socket.io client using sails.sockets.js onconnect event?

Am not able to call socket-client listener using sails.sockets.js onConnect event on server side..
E.g
onConnect: function(session, socket) {
socket.on('chat message', function(msg){
console.log(msg);
console.log("socket.id: " + socket.id);
sails.sockets.broadcast(socket.id, 'chat message', {msg:msg});
});
}
Please let me know whats the correct way of calling back to your socket-client using socket-server events like onConnect..
If you are using standard sails.js socket library:
$(document).ready(function() {
io.socket.on('connect', function() {
});
io.socket.on('chat message', function(data) {
io.socket.post('/routeToAction', {
}, function(data, jwres) {
});
});
});
for newer version, you have to use config/bootstrap.js file for listen events
module.exports.bootstrap = function(cb) {
// handle connect socket first event executes after logged in
sails.io.on('connect', function (socket){
// store facebook token here
});
// handle custom listener for other stuff
sails.io.on('doSomeStuff', function (socket){
// check facebook token match with requested token
});
cb();
};
client : you can simple emit "doSomeStuff" after logged in with facebook and pass token with each request
Finally am become little expert in web sockets who knows back anf forth of push technoligy via websockets..
How to start with websockets :
Step 1: Choose any websocket framework for your application and install socket client on client side and socker server on server side with listeners(imp.).
Step 2: Once you are ready with socket setup on both sides then your client/browser will make a connection after every page load which is listened on server side via onConnect listener or event.
Step 3: Successfull connection on both sides giving you socket object which contains each client socket id which is managed at server side to either join any channel/room or just to make a broadcast or blast.
Remember:
i. Socket object is responsible for defining listeners on both client side and server side. Using socket object you can pass any data to listeners.
ii. Socket connection is very helpful when you trying to push data from client to server and vice-versa.
iii. You can make your small chatter tool with it once you understand as mentioned above.
Will share similar working snippet soon..
//onConnect event on server side
onConnect: function(session, socket) {
console.log("Socket Connect Successfully: " + socket.id );
socket.on('chatAgency', function(data){
sails.sockets.broadcast(data.agencyId,"chatAgency", {message:data.message,agencyId:session.agencyId});
});
},

duplicate websocket writing

I'm new in NodeJS and I would appreciate help with duplicate socket writing.
I have the following code in my client part of application and when something happens, I'm sending an alert to the server:
socket.emit('change', {alertType: ALERT_TYPE});
And on the server side I have this:
var app = require('express')()
, server = require('http').createServer(app)
, io = require('socket.io').listen(server);
server.listen(3000);
io.sockets.on('connection', function (socket) {
socket.on('change', function (data) {
io.sockets.emit('change-done', data);
});
});
And if more people are using the app I get multiple socket writing like this:
debug - websocket writing 5:::{"name":"change-done","args":[{"alertType":"waiting_delivery"}]}
debug - websocket writing 5:::{"name":"change-done","args":[{"alertType":"waiting_delivery"}]}
debug - websocket writing 5:::{"name":"change-done","args":[{"alertType":"waiting_delivery"}]}
And the number of these sockets writings increases as more people are using this. How can I fix this?
Thank you in advance for your help.

How to create a TCP server using Sails.js?

So I'm using Sails.js, and when I run sails lift it works properly in serving the website. However, how can I create a TCP server that also runs when I sails lift and constantly listens for raw TCP messages from clients? I have found this simple TCP server example for Node.js (which obviously will work for Sails):
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');
How can I integrate this into Sails? Do I need to modify the app.js file (which is what I presume gets run when sails lift is entered)? Any ideas?
I'm a little bit late to the party, but recently i had the same requirement and came up with the following code:
let net = require('net');
net.createServer(function (socket) {
socket.on('data', function (data) {
const req = {
url: '/controllername/method',
method: 'get'
};
const res = {
_clientCallback: function _clientCallback(clientRes) {
// TODO: do something useful with clientRes
message = clientRes.body;
if (clientRes.body && clientRes.body.message) {
message = clientRes.body.message;
}
process.stdout.write(message);
}
}
sails.router.route(req, res);
});
}).listen(1338);
Have a look at the project sails-hook-sockets too.

Call event from native WebSocket to Socket.IO server

I have this socket.io server:
var io = require('C:\\Program files\\nodejs\\node_modules\\socket.io').listen(55555);
io.set('destroy upgrade', false);
io.sockets.on('connection', function (socket) {
socket.on('sayHello', function () {
console.log('Hello client!');
socket.emit('sayHello');
});
socket.on('disconnect', function () {
console.log('Goodbye!');
});
});
And I want to connect to the server using the WebSocket class like this:
var socket = new WebSocket('ws://localhost:55555');
I get the connection, but I want to know how can I call an event of the server, example: "sayHello", is that possible? or does Socket.IO use some kind of token in order to avoid spoofing? Thank you!
You should be able to use the socket.io-client module directly from node. It handles the socket.io protocol and everything for you, just like the browser, except in node.

Categories