node.js express - delayed start - node.js

I'm using express for my http server. I want to initialize the database connection first before I start to accept any http connection from client side. Some part of the code is as below.
function connect_to_db(connection_string) {...};
connect_to_db(connection_string);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
This doesn't work because the db connection takes time to be established. Before the connect_to_db is completed, the http server has already been started.
Any advice on how to make the code wait for the db connection to be established first?

you need to initialize server, when you can able to connect to database. You probably need some callback, when you are connected to database. e.g.
connect_to_db(connection_string, function(){
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
}

Related

Net Socket Connections in OpenShift

I am trying to create a net socket Nodejs server for my embedded device to send data to on OpenShift.
I am trying to create this simple echo service
var net = require('net');
var HOST = process.env.OPENSHIFT_NODEJS_IP;
var PORT = process.env.OPENSHIFT_NODEJS_PORT || 3000;
console.log('IP:' + HOST + ' Port:' + PORT);
var server = net.createServer(function(connection) {
console.log('client connected');
connection.on('end', function() {console.log('client disconnected');});
connection.write('Hello World!\r\n');
connection.pipe(connection);
});
server.listen(PORT, HOST , function() {
console.log('server is listening');
});
I according to OpenShift's Port Binding Guide I had my client application connect to Port 8000.
For Testing I am using the following code from my desktop machine.
var net = require('net');
var HOST = 'nodejs-myapplication.rhcloud.com';
var PORT = 8000;
var client = net.connect(PORT, HOST, function() {
console.log('connected to server!');
});
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
client.on('end', function() {
console.log('disconnected from server');
});
The Client Scripts gets to Connected to server and gets stuck there itself. Nothing takes place after that.
Now if I open the address nodejs-myapplication.rhcloud.com:8000 in my browser, the NodeJS Server logs a client connected and disconnected, but when the NodeClient is connected the server doesn't show any update. The Node Client just says connected and stays there without doing anything.
If I run the same scripts locally it works fine, ( Locally i use HOst as 127.0.0.1 and port as 3000).
How can I get a TCP Application to connect to the Openshift NodeJS Server?
The Device will be sending ASCII output over the socket eg. $VAR,12,23,21\r\n
I need to be able to read that data, convert it to JSON and send it out to another server.
It has to be loaded on a platform like DigitalOcean with a firewall enabled.
OpenShift doesn't allow custom ports by default so need a workaround for that.

Node.js tcp sockets and linked Docker containers

I have two node apps in two Docker containers.
Main web app
A profile service using sockets over tcp
I link the Profile Service container to the Main Web App container using this option when running the Docker container
--link srv-profile:srv_profile
And it seems to be linking it just fine. I can say this because I am able to see the following in my Main web app container:
root#8d6247a82b6d:/app# echo $SRV_PROFILE_PORT
tcp://10.1.0.8:4000
root#8d6247a82b6d:/app#
The problem I am facing is that my Main web app container is not able to establish a connection with my Profile Service container. Here is the output when I start my main web app:
root#8d6247a82b6d:/app# nodemon server.js
3 Nov 01:22:43 - [nodemon] v1.2.1
3 Nov 01:22:43 - [nodemon] to restart at any time, enter `rs`
3 Nov 01:22:43 - [nodemon] watching: *.*
3 Nov 01:22:43 - [nodemon] starting `node server.js`
web.main listening on port 4000...
Connection closed
Here is my code for both Profile Service and Main Web App
srv-profile\server.js
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 4000;
// Create a server instance, and chain the listen function to it
// The function passed to net.createServer() becomes the event handler for the 'connection' event
// The sock object the callback function receives UNIQUE for each connection
net.createServer(function(sock) {
// We have a connection - a socket object is assigned to the connection automatically
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
// Add a 'data' event handler to this instance of socket
sock.on('data', function(data) {
console.log('DATA ' + sock.remoteAddress + ':');
console.log(data);
console.log();
// Write the data back to the socket, the client will receive it as data from the server
sock.write('You said "' + data + '"');
});
// Add a 'close' event handler to this instance of socket
sock.on('close', function(data) {
console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort);
});
}).listen(PORT, HOST);
console.log('Server listening on ' + HOST +':'+ PORT);
web-main\server.js
var env = process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var express = require('express'),
logger = require('morgan'),
profileManager = require('./lib/profile-manager');
var app = express();
app.use(logger('dev'));
app.listen(4000, function() {
console.log('web.main listening on port 4000...');
profileManager.connect();
profileManager.disconnect();
});
web-main\lib\profile-manager.js
var net = require('net');
var client = new net.Socket();
var _connect = function() {
client.connect(process.env.SRV_PROFILE_PORT, function() {
console.log('CONNECTED TO: ' + process.env.SRV_PROFILE);
// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
client.write({
action: 'doSomething',
data: '1234',
source: 'web-main'
});
});
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
console.log('DATA: ' + data);
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
};
var _disconnect = function() {
// Close the client socket completely
client.destroy();
};
module.exports = {
connect: _connect,
disconnect: _disconnect
};
Have you tried to run it locally, w/o docker? I made this an exercise for myself and found multiple issues:
As mentioned before, server should bind to 0.0.0.0 to listen on all interfaces
Docker file for server must EXPOSE 4000 (which it seemingly does in your example, since the link works)
Socket.connect() does not accept the docker-style url (i.e. 'tcp://172.17.0.12:4000'), it must be an options object like {host: 'bla', port: '1337'} - use Node's url module to parse the variable provided by docker.
As far as I can see, your client immediately disconnects right after it initiates the connection (the disconnect() call in profile-manager.js)
You can't just write an object to the socket. Sensible choice for encoding would be JSON.stringify()
Moreover, since data received via the socket is a Buffer, using data.toString('utf-8') should result in human-readable output.
Working example can be found on https://github.com/joerx/node-docker-tcp-sockets
If I'm reading your code correctly, you're profile service is only listening on 127.0.0.1. However, the web app is calling from another IP Address. Different containers have different IPs. So the profile service is denying the incoming connection because it is coming in to an invalid IP.

Why is my connection of a NodeJS server (Sails) to another NodeJS Server (Express4) using Socket.IO failing?

I am trying to connect my Node.JS (written using Sails.JS) app to another Node.JS server (Express4 / Socket.io) using socket.io-client.
My Sails Service app/services/Watcher.js looks like
var client = require('../../node_modules/sails/node_modules/socket.io/node_modules/socket.io-client');
// callback of the form function(socket)
exports.connect = function(callback) {
sails.log.debug("will connect socket to", sails.config.watcher.uri, "with Socket.io-client version", client.version);
var socket = client.connect(sails.config.watcher.uri);
socket.on('connect', function(){
sails.log.debug("connected");
socket.on('disconnect', function(){
sails.log.debug("Disconnected");
});
socket.on('error', function(err){
sails.log.debug("Could not connect", err);
});
callback(socket);
});
};
This is invoked from config/bootstrap.js as follows:
Watcher.connect(function(socket){
sails.log.debug("Connected watcher to relay with socket", socket);
});
On the Express side my server relay.js is as simple as:
var app = require('express')(),
http = require('http').Server(app),
io = require('socket.io').listen(http),
port = process.env.RELAY_PORT || 8000;
app.get('/', function(req, res) {
var response = {message: "some response"}; // to be implemented.
res.json(response);
});
http.listen(port, function () {
console.log("Relay listening on port " + port);
});
io.sockets.on('connection', function (socket) {
console.log("Connection opened", socket);
socket.on('disconnect', function () {
console.log("Socket disconnected");
});
});
When I run node relay it dutifully reports
Relay listening on port 8000
When I sails lift my other server it dutifully reports
will connect socket to http://localhost:8000 with Socket.io-client version 0.9.16
But I never see an actual connection.
If I point a browser at localhost:8000 I get the {"message":"some response"} JSON response I expect.
Why isn't my relay server accepting a connection from my socker.io-client app?
The issue here is probably that you're trying to re-use the
socket.io-client from inside of Sails. In general, if you're require()-ing dependencies of Sails directly in your project, you're heading in the wrong direction. In this case, socket.io-client caches configurations and connections, so your require isn't getting a fresh copy.
Instead, do
npm install socket.io-client#~0.9.16 --save
in your project and require with
var client = require('socket.io-client');
that'll give you a fresh copy of the socket client to work with, and avoid any conflicts with the Sails core's version.

Socket.io creating multiple connections

I'm integrating socket.io into my project. I'm using the code below and it's creating 6 connections after the first request. Is this normal?
server.listen(
port,
function()
{
console.log('Node.js server listening on port ' + port);
}
);
server.on(
'connection',
function(socket)
{
console.log('socket.io connection');
}
);
And here is the console.log output:
Node.js server listening on port 3000
socket.io connection
socket.io connection
socket.io connection
socket.io connection
socket.io connection
socket.io connection
You get this result because (as far as I understand) your server object is an instance of node's http.Server class, and is not connected with Socket.IO at all. In your example, 'connection' event is being fired on any request the your node server. It looks like browser sends 6 requests to your node server: page, favicon.ico, and 4 other requests (it might be images, javascripts, css, etc.).
To integrate socket.io into your project you may use the following code:
var http = require('http');
var sio = require('socket.io');
var server = http.createServer(function(req, res) {
//you request handler here
});
var io = sio(server);
io.on('connection', function(socket) {
console.log('socket connected');
//now you can emit and listen messages
});
var port = 3000;
server.listen(port, function() {
console.log('Node.js server listening on port ' + port);
});
And, of course, the official documentation might be very helpful. Good luck :)

Socket.io - Close Server

I have a socket.io server in my app, listening on port 5759.
At some point in my code I need to shutdown the server SO IT IS NOT LISTENING ANYMORE.
How Can I accomplish this?
Socket.io is not listening on an http server.
You have a server :
var io = require('socket.io').listen(8000);
io.sockets.on('connection', function(socket) {
socket.emit('socket_is_connected','You are connected!');
});
To stop recieving incoming connections
io.server.close();
NOTE: This will not close existing connections, which will wait for timeout before they are closed. To close them immediately , first make a list of connected sockets
var socketlist = [];
io.sockets.on('connection', function(socket) {
socketlist.push(socket);
socket.emit('socket_is_connected','You are connected!');
socket.on('close', function () {
console.log('socket closed');
socketlist.splice(socketlist.indexOf(socket), 1);
});
});
Then close all existing connections
socketlist.forEach(function(socket) {
socket.destroy();
});
Logic picked up from here : How do I shutdown a Node.js http(s) server immediately?
This api has changed again in socket.io v1.1.x
it is now:
io.close()
The API has changed. To stop receiving incoming connections you should run:
io.httpServer.close();

Resources