Multiple Rooms Within Dynamic Namespaces in Socket.IO - node.js

I'm using Socket.IO to deploy a real-time drawing canvas application with Node.JS and Express but here's the problem I'm facing:
Even though I created namespaces to connect peers to namespaces according to pathnames they're visiting
(normally — /webrtc/:id), the application does a poor job of isolating two different pathnames. So it also connects two different pathnames but oddly, with a one-sided connection.
For example, if I were to go to localhost:3000/webrtc/1 on one tab and /webrtc/2 on the other, the first tab peer would transmit drawing data to the other one while the second one wouldn't.
P.S it does well within the same pathnames.
P.P.S I mean document.href.pathname by saying pathname.
Here's the source:
SERVER
var io = require('socket.io')(server);
app.get('/webrtc/:id', function(req, res, next) {
className = '/webrtc/' + req.params.id;
nsp = io.of(className);
res.render('webrtc');
nsp.on('connection', function(socket){
socket.on('drawing', (data) => nsp.emit('drawing', data));
});
})
CLIENT
var socket = io(document.location.pathname);

Related

long-running applications and socket.io

I have a web application that accepts an input from the client (browser) and calls an application at the server side with the input. The problem is that the application will run for a long time (about 20s). In order to not block the client (browser) and show the progress to the user, my server side POST function returns immediately and feeds the user
input to the application. Once the application computed the result, I send the result to the client using socket.io. Another twist to the scenario is that the application can not be repeatedly launched and closed (will cause some problem with CUDA) so the whole server side runs just one instance of the application. A sketch of my server-side code looks like the following. Embedded in the code are the three questions that I have searched through the Internet and tried various solutions but could not work out. Any help on them is really appreciated. If this is not the right place to ask, I would be thankful to any feedback about where to ask this question.
var express = require('express');
const{ spawn }= require('child_process');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var darknet = spawn('./darknet', other arguments...) ;
io.on('connection', function(socket){
app.socket = socket;
console.log('A connection has been established');
})
darknet.stdout.on('data',(data) =>{
// This function is called once darknet finished computation and wrote the result to the stdout
// Question 1: now need to send the data back to the client but have no access to any socket here?
})
io.on('connection', function(socket){
//Question 2: how to store this socket so that I can use it in a solution to the Question 1? Can I use session? */
//Question 3: I observed that once the client side refreshed its page (for example, uploaded an image), the previous socket will be closed and a new socket will be established. How do I make sure that I send the output from the application to the right socket since the original one may be invalid when the output is ready to be sent?
})
app.post('/predict', function (req,res){
darknet.stdin.write(user_input+'\n');
res.render();
})

Using Node, Express, (and Socket.io?) to update a page every 1 second

I am a bit new to Node.js and Express, and am currently working on a page where I would like to generate and send messages (from the server) to the client page every 1 second (1250ms, actually). When a user visits the site, I would like the latest message to be broadcasted, with new messages coming in every second after. In other words, every user would see the same message at the same time on the web page, regardless of when they connected to the server.
I have done some searching and have unfortunately have not had any luck playing with code samples online. Here is a ROUGH IDEA to explain:
app.js
'use strict';
var express = require('express');
var app = express();
var http = require( "http" ).createServer( app );
var io = require( "socket.io" )( http );
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/index.html');
});
http.listen(3000, function(){
/* someFunction to generate new LATESTMESSAGE every 1s */
io.on('connection', function (socket) {
socket.emit('news', { messages: LATESTEMESSAGE })
});
});
I assume I would need to send the message via socket.io from the function that generates the LATESTMESSAGE (every 1s when message is generated, send via socket?)? If that is the case, I am unfamiliar with how I would require socket.io in a page that is NOT the app.js (this function would probably be a class, in its own js file), as socket.io requires app and express (see code above).
I appreciate the help! I have spent a good amount of time pondering this today and would appreciate any direction or assistance. Please let me know if I have not supplied enough information.
p.s. the code above definitely would not accomplish what is needed. just a rough outline to show what i am attempting to accomplish
What you're doing looks like half-duplex communication i.e. Only the server sends data to the client, and not the other way around. Socket.io is full duplex communication, i.e. Server and client send data to each other. So technically what would be best for your requirements is Server Sent Events (SSE) using EventStream. Socket.io might be slightly excessive.
Having said that, what you want is to write a Middleware, to which you pass the application. Please take a look at https://expressjs.com/en/guide/using-middleware.html
Basically, your io would be passed in to the middleware functions, so they'd have access to Socket. And the middleware functions in turn would be imported into your app.js.

Socket.io (1.0) + Multiple client connections

So I'm connecting two variable (objects) to the same socket.io server, one's job is to handle public feed and another's to handle private feed with extended functions.
I've attempted the "force new connection" option, however both connections seem to still use utilize the same socket + session Id.
I originally didn't include code because this is so basic, but here you go:
var socket = io(host);
socket.on('connect', function(e){
socket.emit('join', {
channel: stream_channel,
});
});
One is var socket, the other is var socket2. When it connects to the server it emits "join" where:
io.on('connection', function(socket){
socket.on('join', function(d){
socket.join(d.channel);
});
});
I was able to figure this out by:
Subscribing the websocket to multiple rooms
Appending additional variables at each POST to define the room to emit to
I was able to determine that:
Utilizing the same host will always keep the same session id / socket (even with force connection enabled)
Potentially using a different host or namespace would allow a separation in connection
It's better to keep a single connection with multiple rooms

How to send a temporary chunk of html and js to a running app on node.js

I just got my first app up and running on Node.js. As of now, it is simply serving up a static file. But I have a few ideas that will be implemented down the road so I'm going ahead and getting Node setup so I'll be ready for it when that time comes.
// get modules
var express = require('express');
var fs = require('fs');
// create app instance
var app = express();
// static files middleware
app.use("/assets", express.static(__dirname + '/assets'));
// main route
app.get('/', function(req, res) {
var html = fs.readFileSync('assets/views/main.html', 'utf8');
res.send(html);
});
// make web server listen on specific port
app.listen(8080);
NOTE: I realize I don't need Express to serve one route, but I figured what's the harm in getting a head start on that as well?! :)
The first idea i had is to make a way to let all users currently using the app that there has been an update and that they must refresh their browser. There is no need to save the current state of the app as it is pretty basic.
So, if I am a user, I'm using the app and boom, I get a pretty little modal-window-alert-notification thingy letting me know that I need to refresh.
Also, if some user loads the app AFTER I have sent the alert, that user should not see the alert at all (because they should already be seeing the new changes).
I have done some googling on the subject and I'm just not satisfied with the examples i found. I do not think I want to have to update a notifications.xml file (which node.js would be watching) to push a new notification.
One solution I can think of would be to make a command that can be executed from the command line that will (somehow) send a new notification to the app. Perhaps using something like Grunt.js (I'm not sure if it would be a good fit for this as I've never used it). Basically, once the notification has been sent, all traces of it should disappear. That's why I think a command line approach would be good.
Here's my question: How (generally speaking) should I implement something like this? I am a Node.js newbie but I am pretty comfortable with javascript and the command line.
Please feel free to offer up any alternative solution you think would be better for me (other than a command line approach), or any tools that you think could help me.
Thanks!
If you want to push updates to a web client, one way is to use something like Socket.io. This creates a two-way pipe between client and server that you can use to asynchronously push updates through.
Sample server:
var app = require('express').createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Sample client:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
alert('New news has come in! Please refresh your page!');
socket.emit('my other event', { my: 'data' });
});
</script>
The other option is to poll from the client using Javascript to actively look for updates. You would need to keep some state on the server for each client that would determine if that client required an update. The client would then make a get request on some timer interval (once a second, for example) to a secondary route and the server would reply with 'Yes, you need an update' or 'No, you don't need an update'. If yes, the client Javascript would then pop up your modal box and tell the user to refresh.

Can socket.io client connect to two different servers/ports?

Can socket.io client connect to two different ports on the same server?
Can socket.io client connect to two different server?
Sure:
var io1 = require('socket.io').listen(8001);
io1.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
});
var io2 = require('socket.io').listen(8002);
io2.sockets.on('connection', function (socket) {
socket.emit('flash', { hello: 'world' });
});
Perhaps this is an interesting read: (from github)
// connect at the same host / port as your website
var socket = io.connect();
// different port or host
var socket = io.connect('http://url.com');
// secure
var socket = io.connect('https://localhost');
Can socket.io client connect to two different ports on the same
server?
I assume both machines share same domain. I believe it can use long-polling(websockets, flashsockets, etc also work), even passing along cookie. But I still need to test this on Internet Explorer because that browser never does what I want...
Can socket.io client connect to two different server?
The big question is if those both machines are on different domains. If on same domain it will work just fine even passing along cookie(s). If they are on different domains then on some browser we fall-back to json-p transport(worst transport imaginable), but it will work. Unfortunately then the cookie is not passed along, because of same origin policy. Right now I am toying to get around this cookie restriction(hard problem)...

Resources