How to run multiple node.js servers - node.js

I have two Express servers running on different ports. The first server (web server) provides a website and the second server (data server) emits data every 100 ms using socket.io.
When I open the website in the browser the data appears as expected. But when I then open the website in a second browser, all the emitted data in the first browser slows remarkably down until the second browser is done loading the site.
I should probably mention that the application is running on a Raspberry Pi. The website loading time is not so critical, but the data emission is.
Is there some way to run the node.js servers so they won't be affected by the load on each other?
Right now the web server is in the main app.js file that is run by node and the data server is a module required by the web server. Something like this:
app.js:
var express = require('express');
var data = require('data-server.js');
var app = express();
// Web server setup and handling (mostly Express defaults)
app.listen(3000);
module.exports = app;
data-server.js:
var app = require('express')();
var server = require('http').Server(app).listen(3001)
var io = require('socket.io')(server);
// Socket.io code that emits data every 100 ms
module.exports = io;
Update
Turns out it was my database query that was holding on to node so it couldn't emit because the emission function was waiting for the database to be free.

You should use the same port and the same node process for both your regular HTTP traffic and your websocket traffic. It would minimise the performance impact on your raspberry pi. Example :
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendfile('index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});

Method 1: Infinite-Servers.js : Start 1000 servers in one run
const express = require('express')
var app=new Array(10)
for (let i = 3000; i <= 4000; i++) {
app[i]=express()
app[i].get('/',(req,res)=>res.send({'port': i}))
app[i].listen( i,()=>console.log('port', i,"started"))
}
Method 2: MultiServers.js : Start 2 servers:
const express = require('express')
server=express()
server2=express()
server.get('/',(req,res)=>res.send({"server":"3001","name":"aakash4dev","data":"some data 1"}))
server2.get('/',(req,res)=>res.send({"server":"3002","name":"aakash4dev","data":"some data 2"}))
server2.get('/somethig',(req,res)=>res.send({"server":"3002","name":"aakash4dev","data":"some data 2"}))
server.listen(3001)
server2.listen(3002)
Method 3: SepetareInfiniteServers.js
If you want to keep all files separately, e.g. port1.js port2.js port3.js .... port1000.js, all in different files and start all servers on a single run, then use module.exports (official docs: https://nodejs.org/api/modules.html#moduleexports ) along with the first InfiniteServers.js codes above. codes will look like this:
var portsData=new Array(3)
const express = require('express')
const cors=require('cors')
var app=new Array(3)
for (let i = 1; i <= 3; i++) {
portsData[i]=require('./port'+i)
app[i]=express()
app[i].use(cors())
app[i].get('/',(req,res)=>{
let req_requestedData={"name":"aakash4dev"}
res.send(require('./port1.js').fun1({req_requestedData,"our-Response":"Im server"}))
})
app[i].listen( i,()=>console.log('port', i,"started"))
}
note: import cors module and use app[i].use(cors()) in array or app.use(cors()) in normal servers to remove error cors policy no 'access-control-allow-origin'

Related

Socket IO returning error client side with polling.js

So I have this web application that is am moving to my personal website but I've been encountering a few errors and I haven't been able to find a solution for this one:
For some reason I get
polling.js:311 GET https://kayden.dev/socket.io/?EIO=4&transport=polling&t=O35Ebas 404
on the client side that appears every few seconds.
My code does need some cleaning up so I won't be showing everything but here. The server side code looks something like this:
const http = require('http');
const express = require('express');
const socket = require('socket.io');
const path = require('path');
let app = express();
let port = app.get('port');
let users = [];
let amountOnline = 0;
//send static files from public to the client
let server = app.listen(port, function(){
console.log('listening to requests on port '+ port);
});
//first parameter is the /whatever that goes after the url
app.use("/skyfighters", express.static(__dirname + '/public/'));
//setup socket
let io = socket(server);
io.serveClient(true);
And the client side code only has let socket = io.connect();
that actually executes at the moment with this error happening
Any help is appreciated, this is the first time I migrate a node app the a web server so I'm quite unfamiliar with it.
Thanks!

socketio, client can connect to server if hosted locally, but returns error when trying to connect to server hosted on seperate vserver

I am trying to make a simple server with socket.io and express and connect to it through a website.
when i followed a tutorial on socketio with localhost, everything worked fine, but when i put the server on a vserver, and tried to connect to it, i got this error:
Failed to load resource: net::ERR_SSL_PROTOCOL_ERROR
as well as:
GET https://54.53.0.254:47185/socket.io/?EIO=4&transport=polling&t=O09jjrs net::ERR_SSL_PROTOCOL_ERROR
here is my server code:
const express = require('express');
const app = express();
const server = app.listen(47185);
const socket = require('socket.io');
const io = socket(server)
console.log('server running on port 47185');
io.sockets.on('connection', newConnection);
function newConnection(socket) {
console.log('new connection: ' + socket.id);
socket.on('input', inputLog)
function inputLog(data) {
socket.broadcast.emit('input', data);
console.log(data);
}
}
and here is my client code (this is all that relates to socket.io, the rest is just for the website)
var options = {
rejectUnauthorized:false
}
var socket;
socket = io.connect('89.58.0.199:47185', options);
socket.on('input', foreignInput)
function foreignInput(data) {
terminal_animate('\n' + data)
}
i have tried many different fixes and googled everything i can think of, and i'm just not sure what the problem is.
can anyone help me out with this issue? thanks in advance.
In the documentation, according to the Client Initialization part, in node.js you should provide the protocol when connecting to the server.
// the following forms are similar
const socket = io("https://server-domain.com");
const socket = io("wss://server-domain.com");
const socket = io("server-domain.com"); // only in the browser when the page is served over https (will not work in Node.js)
The first two example shows the secure https/wss as protocol, for that you need to serve the required files from the server, example in the documentation.
With http/ws as protocol it should work, but the communication will not be secure.
The Server Initialization / With Express shows an example to call .listen on the return value of createServer from the http module, with the app given as a parameter.
const express = require("express");
const { createServer } = require("http");
const { Server } = require("socket.io");
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, { /* options */ });
io.on("connection", (socket) => {
// ...
});
httpServer.listen(3000);
With a caution that says:
Using app.listen(3000) will not work here, as it creates a new HTTP server.

How to ensure requests to my servers functions only by a single origin / UI?

I have a node.js server that has HTTP CRUD functions to my mongoDB.
And an Android application that sends requests though those functions.
I would like to ensure that my server will answer requests from specific origins.
For example: only answer requests from the android app, or my pc postman's requests.
How can I ensure that no one else sending requests using the same urls and ports will get answered?
This is my server.js file:
const express = require('express');
const MongoClient = require('mongodb');
const bodyParser = require('body-parser');
var db = require('./config/db');
var app = express();
const port = 8000;
app.use(bodyParser.json());
MongoClient.connect(db.url, (err, database) => {
if (err) return console.log(err)
db = database.db("getremp")
require('./app/routes')(app, db);
app.listen(process.env.PORT || port, () => {
console.log("Express server listening on port %d in %s mode - We Are lIVE!",app.settings.env.port, app.settings.env);
});
})
and my index.js:
const noteRoutes = require('./note_routes');
module.exports = function (app, db) {
noteRoutes(app, db);
};
You can control this with :
Send a specific header with your datas containing a secret key, then control the header in your node app How to check headers in nodejs?
Use HMAC in order to authenticate the user and control the integrity of datas : Node Hmac Authentication
But you've to remember that all traffic going out from an mobile app can be intercept (with Fiddler for example). Never use a static (non-dynamic) value to ensure authentication

Socket.io doesn't correctly attach to http server in express application

I'm pretty new to NodeJS and trying to get Socket.IO running with an Express application. I've tried to stick to the docs and tutorials as close as possible, but in the end, socket.io.js cannot be found on client side.
The server is being started as follows:
var app = require('../app');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() { debug('...') } );
Routing/serving pages:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
Including socket.io:
var express = require('express');
var http = require('http').Server(express);
var io = require('socket.io')(http);
And in the HTML file, for clients:
<script src="/socket.io/socket.io.js" type="text/javascript">
But when loading the page, this JS-file is never found. I suspect that including socket.io via that previously created http server is somehow wrong... Or am I missing something else?
Update
I just found out that the snipped that includes socket.io is executed before the server is started (first snippet). They're in different files and the server-start one (named www.js) is configured as "start" script in package.json, the other one (websockets.js) required indirectly by that.
If I put
var io = require('socket.io')(server);
at the end of www.js, everything works just fine. But is there a way to do it from websockets.js, which is loaded before, e.g. by a server start callback function?
Try specifying the full path, like this
<script src="http://localhost:8000/socket.io/socket.io.js"></script>
And connect to your server from client side:
var socket = io.connect('http://localhost:8000/');
also check if socket.io module is available in your node_modules directory.

Share express port over processes in node.js

So I switched from child.fork to cluster.fork to spawn chatbots that I run, as clusters share tcp ports. However, I can't seem to get the clusters to listen on the same port.
code:
var cluster = require('cluster');
var express = require('express');
if (cluster.isMaster) {
cluster.fork({path:'hello'});
cluster.fork({path:'goodbye'});
} else {
var web = express();
web.get("/"+process.env.path,function (req,res){
return res.end("hello, "+process.env.path);
});
web.listen(3000);
}
This is half working. I get no EADDRINUSE errors now, but only one of the paths is showing up.
It's not working for lots of reasons.
express.express dont exist. You are looking for plain express method
process.evn dont exist. You are looking for process.env
You are not returning anything to the client in your route. You should use res.end or another method to response the client. Check the http module documentation or the express one.
The workers can share tcp connections. The master can not.
Some code that works:
var cluster = require('cluster');
var express = require('express');
if (cluster.isMaster) {
cluster.fork({path:'hello'});
} else {
//this is in a required file
var web = express();
web.get("/"+process.env.path, function(req,res){
res.end("hello world!");
});
web.listen(3000);
}
If you want to use more than one worker, just fork more in the if(cluster.isMaster) condition.

Resources