Restarting Web server when config file changes using NodeJS - node.js

I have a simple and working web server written in NodeJS as below:
var http = require("http");
var fs = require("fs");
console.log("Web server started");
var config = JSON.parse(fs.readFileSync("./private/config.json"));
var server = http.createServer(function(req,res){
console.log("received request: " + req.url);
fs.readFile("./public" + req.url,function(error,data){
if (error){
// Not sure if this is a correct way to set the default page?
if (req.url === "/"){
res.writeHead(200,{"content-type":"text/plain"});
res.end("here goes index.html ?");
}
res.writeHead(404,{"content-type":"text/plain"});
res.end(`Sorry the page was not found.\n URL Request: ${req.url}`);
} else {
res.writeHead(200,{"content-type":"text/plain"});
res.end(data);
}
});
});
Now I want my web server to restart and listen to a new port when port number changes in the config file. So I add below code:
fs.watch("./private/config.json",function(){
config = JSON.parse(fs.readFileSync("./private/config.json"))
server.close();
server.listen(config.port,config.host,function(){
console.log("Now listening: "+config.host+ ":" +config.port);
});
});
This works fine and when I change the port on config file, I can access my web server on the new port. However, I also can access it on the previous port as well. I thought I am closing my web server on the previous port before I listen to the new port. What am I missing ?
I appreciate your help :)

As Mukesh Sharma mentioned, Server.close() stops accepting new connections and keeps existing connections. That is, server stays open for all alive sockets(until they naturally die due to keep-alive time) but no new sockets will be created.
I found out this question can be a possible duplicate of this question
So I followed the suggested solution mentioned by Golo Roden in the link and it worked. Basically you need to remember open socket connections and destroy them after you close the server. Here is my modified code:
var http = require("http");
var fs = require("fs");
console.log("Web server started");
var config = JSON.parse(fs.readFileSync("./private/config.json"));
var server = http.createServer(function(req,res){
console.log("received request: " + req.url);
fs.readFile("./public" + req.url,function(error,data){
if (error){
// Not sure if this the correct method ?
if (req.url === "/"){
res.writeHead(200,{"content-type":"text/plain"});
res.end("welcome to main page");
}
res.writeHead(404,{"content-type":"text/plain"});
res.end(`Sorry the page was not found.\n URL Request: ${req.url}`);
} else {
res.writeHead(200,{"content-type":"text/plain"});
res.end(data);
}
});
});
server.listen(config.port,config.host,function(){
console.log("listening: "+config.host+ ":" +config.port);
});
var sockets = {}, nextSocketId = 0;
server.on('connection', function (socket) {
// Add a newly connected socket
var socketId = nextSocketId++;
sockets[socketId] = socket;
console.log('socket', socketId, 'opened');
// Remove the socket when it closes
socket.on('close', function () {
console.log('socket', socketId, 'closed');
delete sockets[socketId];
});
});
fs.watch("./private/config.json",function(){
config = JSON.parse(fs.readFileSync("./private/config.json"))
console.log('Config has changed!');
server.close(function () { console.log('Server is closing!'); });
for (var socketId in sockets) {
console.log('socket', socketId, 'destroyed');
sockets[socketId].destroy();
}
server.listen(config.port,config.host,function(){
console.log("Now listening: "+config.host+ ":" +config.port);
});
});

Related

Node.js send Server input to Client. Warning about memory leak. What is my mistake? And how does node.js run code?

Server:
var net = require('net');
var stdin = process.openStdin();
var client_list = [];
var server = net.createServer(function(connection) {
//console.log('client connected');
connection.on('error', function(e){
if(e.code == 'ECONNRESET'){
console.log('Client dissconeccted');
}
});
//connection.write('Hello World!\r\n');
stdin.addListener("data", function(d) {
// note: d is an object, and when converted to a string it will
// end with a linefeed. so we (rather crudely) account for that
// with toString() and then trim()
console.log("you entered: [" + d.toString().trim() + "]");
connection.write(d.toString().trim());
});
connection.pipe(connection);
});
server.listen(9999, function() {
console.log('server is listening');
});
Client:
var net = require('net');
var HOST = 'localhost';
var PORT = 9999;
//var client = new net.Socket();
var client = net.connect(PORT, HOST, function(){
console.log('connected to server! ' + HOST + ':' + PORT);
//client.write('I am Superman');
});
client.on('data', function(data) {
var data = data.toString();
console.log(data);
//If data starts with JS add injection functionallity
if (data === "END"){
client.end();
console.log("ENDING!")
}
else if (data === "poo"){
console.log("HOLY SHIT!")
}
});
//Keep trying to connect!
client.on('error', function(e) {
console.log('Parent connection error');
//client.end();
client.connect(PORT, HOST);
});
client.on('end', function() {
console.log('disconnected from server');
});
/*var client = net.connect({port: 8080}, function() {
console.log('connected to server!');
});*/
So what happens is that it keeps adding listeners(?) and warns me at 11 listeners with the message:
"Possible EventEmitter memory leak detected. 11 data listeners added.
Use emitter.setMaxListeners() to increase limit".
Why is this? I have tried fixing this by moving stdin.addListener() but it either doesn't take the input at all or the problem persists. Am I onto something? And how is code run in node, is it a loop?
Thanks in advance!
Have run both the client and server scripts. I can't reproduce the error message that you're getting. I'm running the code on Ubuntu - nodejs 6.9.5, npm 5.4.2. Could you post the contents of your package.json file?
Update: had a look online. seems like a known old bug in Node. https://github.com/nodejs/node-v0.x-archive/issues/5108

Node server cannot open specified port

I am trying to write a program that allows me to communicate with a device using the serial port. To do so, I am using the following code :
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var SerialPort = require("serialport");
var port = new SerialPort("/dev/ttyS1");
app.use(express.static(__dirname+"/../.."));
app.use(express.static(__dirname+"/../../../bower_components/"));
io.on('connection', function(socket) {
console.log('new connection');
socket.on('message', function (message) {
//console.log('Position : ' + message); //envoi port ... à la place
//port.on('open', function() {
port.write(message, function(err) {
if (err) {
return console.log('Error on write: ', err.message);
}
});
//});
});
});
server.listen(8080, function() {
console.log('server up and running at 8080 port');
});
However, the issue here is that the port never seems to open, but the value we are supposed to send is still printed in the console,and the /dev/tty (which represents the console) is opened, but the /dev/ttyS1 do not get opened. The following screenshot is obtained after executing
sudo strace -e open,write node server.js
According to the documentation, the port is supposed to open automatically when we instantiate the SerialPort object.
So, are there any issues in my code or is there any better way to do this ?

Node.js express websocket not broadcasting to all connected clients

Im trying to create a node websocket for messaging and broadcasting using openshift. Below is my code.
var WebSocketServer = require('ws').Server;
var http = require('http');
var ipaddr = opneshift_ip;
var port = openshift_port;
var server = http.createServer();
var wss = new WebSocketServer({server: server, path: '/connectserv'});
wss.broadcast = function(data) {
for(var i in this.clients) {
console.log(this.clients[i]);
this.clients[i].send(data);
}
};
wss.on('connection', function(ws) {
console.log('a client connected');
ws.on('message', function(data) {
console.log('>>> ' + data);
ws.send('got '+data);
if (data == 'broadcst') {
console.log('broadcst');
wss.broadcast('Hi All');
}
});
ws.on('close', function() {
console.log('Connection closed!');
});
ws.on('error', function(e) {
console.log(e);
});
});
console.log('Listening at IP ' + ipaddr +' on port '+port);
server.listen(port,ipaddr);
When any client connects, console writes "a client connected".
When any client sends message, console writes ">>> message" and im getting the same at client as well ("got message")
But when multiple clients are connected, if i want to broadcast a message to all connected clients, i send "broadcst" as message. Than goes into
if (data == 'broadcst') {
console.log('broadcst');
wss.broadcast('Hi All');
}
But only the client which sends get the message.
How to make all clients to get the message?
Does each client creates separate session?
How to use redis here?
Any quick help appreciated.
Thanks.
Try
wss.broadcast = function(data) {
for(var i in wss.clients) {
console.log(wss.clients[i]);
wss.clients[i].send(data);
}
};
broadcasting with wss

Under heavy load, client connecting to a socket.io may miss the first packet with node.js

I am on Node.js v4.1.1 and working with socket.io
when client connected to server socket and start exchanging packages at that time first packet missed on server.
have you guys any idea what is the reason behind this? Please note that we have around 900 connection at a time.
var http = module.exports = require('http');
var app = module.exports = express();
var httpsOptions = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('certificate.crt')
};
var Server = https.createServer(httpsOptions, app);
var io = module.exports = require('socket.io').listen(Server);
io.set("transports", ["xhr-polling", "web socket", "polling", "htmlfile"]);
io.sockets.on("connection", function(socket)
{
client.on('msg', function(request)
{
console.log("event get --> " + request);
});
client.on('error', function(exc)
{
console.log("ignoring exception: " + exc);
});
client.on('ping', function(request)
{
client.emit('pong', request);
client.removeListener('ping', function() {});
});
client.on('disconnect', function(reason)
{
console.log("socket disconnect " + reason);
});
});
In this case actually error not in socket or node.js. Error in mongodb , mongodb take so much load so all event's are late. Also new connection take load in sign up process.we just increase the configuration of mongodb and all working well.

NodeJS help proxy TCP port data to web socket

I'm trying to proxy json data from a private TCP port 13854 to a public web socket on port 8080. Why can't I get any data when browsing http://localhost:8080?
var http = require('http').createServer(httpHandler),
fs = require("fs"),
wsock = require('socket.io').listen(http),
tcpsock = require('net');
var proxyPort = 8080;
var serviceHost = 'localhost';
var servicePort = 13854;
function httpHandler (req, res) {
res.setHeader("Access-Control-Allow-Origin", "http://example.com");
res.end();
}
http.listen(proxyPort);
console.info("HTTP server listening on " + proxyPort);
wsock.sockets.on('connection', function (socket) {
var tcpClient = new tcpsock.Socket();
tcpClient.setEncoding("ascii");
tcpClient.setKeepAlive(true);
tcpClient.connect(servicePort, serviceHost, function() {
console.info('CONNECTED TO : ' + serviceHost + ':' + servicePort);
tcpClient.on('data', function(data) {
data = "" + data
//send format request to socket
if (data[0] != '{'){
s.write(JSON.stringify({
enableRawOutput : false,
format : "Json"
}) + "\n");
return;
}
console.log('DATA: ' + data);
socket.emit("httpServer", data);
});
tcpClient.on('end', function(data) {
console.log('END DATA : ' + data);
});
});
socket.on('tcp-manager', function(message) {
console.log('"tcp" : ' + message);
return;
});
socket.emit("httpServer", "Initial Data");
});
THANKS!
First of all, change the line
res.setHeader("Access-Control-Allow-Origin", "http://example.com");
to
res.setHeader("Access-Control-Allow-Origin", "*");
Because you are browsing to localhost, your request will be rejected because the origin is not http://example.com.
Secondly, in order to receive data, you must setup a web socket connection from the client. Just browsing to http://localhost:8080 creates an http connection and not a web socket connection.
I propose to create an HTML page locally and use that by double-clicking on it (instead of going through your server); later you can host the page on your node.js server.
Look at the examples on http://socket.io to correctly create a socket.io client.
I solved the problem by reorganizing my code and keeping the sockets separated. For whatever reason, it seems that Access-Control-Allow-Origin is not needed. I am using a Chrome plugin called "Simple Web Socket Client" to get around needing to write my own client.
var ws = require("nodejs-websocket"),
net = require("net");
var server = ws.createServer(function(conn) {
conn.on("close", function(code, reason) {
console.log("Connection closed");
});
}).listen(8080);
var tcp = new net.Socket();
console.log('connecting to 127.0.0.1:13854');
tcp.connect(servicePort, '127.0.0.1', function() {
//this socket requires sending data on connection
tcp.write(JSON.stringify({
enableRawOutput: false,
format: "Json"
}) + "\n");
});
tcp.on("data", function(data) {
if (server == null || server.connections == null) {
return;
}
//broadcast message:
server.connections.forEach(function(conn) {
conn.sendText(data);
});
}

Resources