Reconnect to TCP/IP socket on NodeJS - node.js

I use "net" library to create TCP connection on my nodeJs.
root.socket = net.createConnection(root.config.port, root.config.server);
I'm trying to handle error when remote server is down and reconnect in Cycle.
root.socket.on('error', function(error) {
console.log('socket error ' + error);
root.reconnectId = setInterval(function () {
root.socket.destroy();
try {
console.log('trying to reconnect');
root.socket = net.createConnection(root.config.port, root.config.server);
} catch (err) {
console.log('ERROR trying to reconnect', err);
}
}, 200);
}
The trouble is that in case of remote server shutdown I still get en error and my nodeJS server stops.
events.js:72
throw er; // Unhandled 'error' event
^ Error: connect ECONNREFUSED
at errnoException (net.js:904:11)
at Object.afterConnect [as oncomplete] (net.js:895:19)

You will need something like this:
var net = require('net');
var c = createConnection(/* port, server */);
function createConnection(port, server) {
c = net.createConnection(port, server);
console.log('new connection');
c.on('error', function (error) {
console.log('error, trying again');
c = createConnection(port, server);
});
return c;
}
In your case you are creating a new connection but you don't attach any error listener, the error is raised somewhere else in the execution loop and can not be caught by the "try / catch" statement.
P.S. try to avoid using "try / catch" statement, error handling in Node.JS is made using error listeners and domains, it can be useful only for JSON.parse() or other functions that are executed synchronously.

Related

Using setInterval with socket.write

This is the code that works but it writes the data just once:
var net = require('net');
var PORT = 3000;
var client = new net.Socket();
client.connect(PORT, function(){
client.write('{printing}');
})
I am looking to write the same thing every few seconds. Wrote the below code but it doesn't seem to work:
client.connect(PORT, function(){
setInterval(function(){
client.write('{ printing }');
},10000);
})
Following is the error that I keep getting:
node:events:355
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at afterWriteDispatched (node:internal/stream_base_commons:160:15)
at writeGeneric (node:internal/stream_base_commons:151:3)
at Socket._writeGeneric (node:net:773:11)
at Socket._write (node:net:785:8)
at writeOrBuffer (node:internal/streams/writable:395:12)
at Socket.Writable.write (node:internal/streams/writable:340:10)
at Timeout._onTimeout (/app/src/index.js:135:14)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
Emitted 'error' event on Socket instance at:
at emitErrorNT (node:internal/streams/destroy:188:8)
at emitErrorCloseNT (node:internal/streams/destroy:153:3)
at processTicksAndRejections (node:internal/process/task_queues:81:21) {
errno: -32,
code: 'EPIPE',
syscall: 'write'
}
[nodemon] app crashed - waiting for file changes before starting..
This is how I fixed it:
client.connect(PORT, function(){
client.write('printing')
})
//adding drain if the buffer gets full
client.on('drain',()=>{
console.log("draining the buffer")
setTimeout(() => {
client.write('printing')
})
//reading the response recieved : ("ok")
client.on('data', (data) => {})
//in case of an error, closing the connection
client.on('error',err => {}).on('close',() => {
setTimeout(() => {
client.connect(PORT, function(){
client.write('printing')
})
},40000)
})
In this context, the EPIPE error probably means that you're trying to write to a socket that has been closed. Since the setInterval() example you show keeps going forever, that probably means that the socket you originally connected gets closed at some point, but your setInterval() is still firing and trying to write to it.
You don't show the overall context of what you're trying to accomplish here to know exactly what to suggest, but at a minimum, you need to call clearInterval() to stop the timer whenever the socket it's trying to write to gets closed, either on purpose or because of error.
Here's an example for how you could debug if this is what is happening to you:
const net = require('net');
const PORT = 3000;
const client = new net.Socket();
let timer;
function disableTimer() {
if (timer) {
clearInterval(timer);
timer = null;
}
}
client.on('error', err => {
console.log("socket error", err);
disableTimer();
}).on('close', () => {
console.log("socket closed");
disableTimer();
});
client.connect(PORT, function(){
timer = setInterval(function(){
client.write('{ printing }');
},10000);
});

How can I gracefully handle a failed tcpSocket.connect attempt?

The following code causes an error when there is no existing TCP server to communicate with on the specified host:
const net = require('net');
const argv = require('minimist')(process.argv.slice(2));
try {
var tcpSocket = new net.Socket();
tcpSocket.connect(argv.tcpport, argv.tcphost, function onConnected() {
console.log('connected');
tcpSocket.on('data', function onIncoming(data) {
console.log(data);
});
tcpSocket.on('close', function onClose(data) {
tcpSocketConnected = false;
});
tcpSocketConnected = true;
});
} catch (err) {
console.log("PRINT ME: ", err);
}
Error:
events.js:183
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 127.0.0.1:1906
at Object._errnoException (util.js:992:11)
at _exceptionWithHostPort (util.js:1014:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1186:14)
I am unable to catch the error even though I wrap the code in a try...catch.
Why does my catch block not catch the error?
How can I gracefully handle the error?
You should be able to explicitly handle the error event using event emitter api (same way as you handled close and data):
tcpSocket.on('error', handleError)
From Docs:
Event: 'error'#
Added in: v0.1.90
<Error>
Emitted when an error occurs. Unlike net.Socket, the 'close' event
will not be emitted directly following this event unless server.close()
is manually called. See the example in discussion of server.listen().

ECONNREFUSED in Node http module

When a remote site is off-line I am getting this error in my consuming client (Node.js v0.12.0 with the http module):
Uncaught exception: connect ECONNREFUSED
Error: connect ECONNREFUSED
at exports._errnoException (util.js:746:11)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:983:19)
The code I'm currently using looks like this:
var req = http.request(options, function (res) {
res.on('socket', function (socket) {
socket.setKeepAlive(true, 0);
socket.setNoDelay(true);
});
res.on('end', function () {
log.debug('Success');
}).on('error', function () {
log.error('Response parsing failed');
});
}).on('error', function () {
log.error('HTTP request failed');
});
req.write(packet);
req.end();
The "error" event is never fired when the ECONNREFUSED occurs, I've tried using the "clientError" event but this is not fired either.
How can I capture this error?
Extracted from: https://stackoverflow.com/a/4328705/4478897
NOTE: This post is a bit old
The next example is with the http.createClient but i think it could be the same
Unfortunately, at the moment there's no way to catch these exceptions directly, since all the stuff happens asynchronously in the background.
All you can do is to catch the uncaughtException's on your own:
process.on('uncaughtException', function (err) {
console.log(err);
});
Maybe that helps you!
More this: https://stackoverflow.com/a/19793797/4478897
UPDATE:
did you tried to change log.error() to console.error() ???

Node.js Error : connect ECONN Refused

I am new to Node.js and am unable to resolve this error:
Error: connect ECONNREFUSED
at errnoException (net.js:901:11)
at Object.afterConnect (as oncomplete) (net.js:892)
The code I was trying out follows :
var async = require('async'),
request = require('request');
function done(err,results) {
if (err) {
throw err;
}
console.log('Done ! results: %j',results);
}
var collection = [1,2,3,4];
function iterator(value,callback) {
request.post({
url: 'http://localhost:8080',
body: JSON.stringify(value)
}, function (err,res,body){
if (err) {
callback(err,body && JSON.parse(body));
}
});
}
async.map(collection,iterator,done);
ECONNREFUSED – Connection refused by server error
A port is being blocked can be the root cause of this issue, check if your connection is being blocked or even the changed default port can also cause this issue. Identify which app/service you are connecting to and its port is being blocked or changed.
And in your case check whether the application is hosted on port: 8080 or not.
But, this most likely occurs with FileZilla.

How to deal with 'read ETIMEDOUT' in Node.js?

I have a pub/sub model using Node.js to transmit data from one client to another client. Besides, the server also records everything received and sends it to new clients.
However, some data corrupted when transfer, and I got error like:
Error with socket!
{ [Error: write EPIPE] code: 'EPIPE', errno: 'EPIPE', syscall: 'write' }
Error with socket!
{ [Error: read ETIMEDOUT] code: 'ETIMEDOUT', errno: 'ETIMEDOUT', syscall: 'read' }
I don't know how to properly handle these errors. It looks like the client is down.
Since the server is only a proxy like a server, it doesn't really know what data means. I have no idea how to validate every data pack before meeting these errors.
Here is my code:
// server is an object inheriting from net.Server
server.on('listening', function() {
var port = server.address().port;
}).on('connection', function(cli) {
cli.socketBuf = new Buffers();
cli.commandStarted = false;
cli.dataSize = 0;
cli.setKeepAlive(true, 10*1000);
cli.setNoDelay(true);
cli.on('connect', function() {
server.clients.push(cli);
}).on('close', function() {
var index = server.clients.indexOf(cli);
server.clients.splice(index, 1);
}).on('data', function (buf) {
server.emit('data', cli, buf);
if(op.autoBroadcast) {
_.each(server.clients, function(c) {
if(c != cli) c.write(buf);
});
}
}).on('error', function(err) {
console.log('Error with socket!');
console.log(err);
});
}).on('error', function(err) {
console.log('Error with server!');
console.log(err);
});
// ...
// room.dataSocket is an instance of server beyond
room.dataSocket.on('data', function(cli, d) {
// bf is a buffered file
bf.append(d);
room.dataFileSize += d.length;
}).on('connection', function(con){
bf.readAll(function(da) {
con.write(da);
});
});
If you get an EPIPE or indeed any error when writing, the peer has closed or the connection has been dropped. So you must close the connection at that point.
If you get a read timeout the inference is that either you have set an unrealistically short timeout or else the peer has failed to deliver in time: in the second case once again you should assume the connection is down, and close it.

Resources