Search code examples
node.jsapisocketsreconnect

nodejs NET api bug? Seeking flawless reconnect fix


I think there may be an issue with the Nodejs v5.3.0 NET api. I am wanting to rely on the socket.remoteAddress field flipping to undefined when the socket is destroyed.

  • socket.remoteAddress The string representation of the remote IP address. For example, '74.125.127.100' or '2001:4860:a005::68'. Value may be undefined if the socket is destroyed (for example, if the client disconnected).

The challenge here is the may language above (bold added for emphasis).

Context: I'm writing a MEaN app that uses sockets to communicate with a remote deviec. The connection is often disconnected and I need to seamlessly reconnect it before use. I have the various functions needed to transmit call connect() before they want to transmit to ensure the connection is live.


UPDATED WITH FIX per mscdex:

if ( !client.readable )
    client.connect(PORT,HOST);
else
    logger.debug('Attempt to reconnect on an active connection. Ignored.');

client.readable provides immediate status on the network connection even if the intent is to write to the connection. client.writable is buffered and thus 'lies' (is overly optimistic) about the connection being present or able to be established.


The below is working code:

var logger = require('winston');
var net = require('net');
var client = new net.Socket();

var init = function() {
    logger.info('Calling connect now...' );
    connect();
};
exports.init = init;

var output = function(action, id) {
    connect();
    //Transmit stuff  here
};
exports.output = output;

var connect = function() {
    // Check to see if remoteAddress is undefined. If so, then connect
    logger.debug('Test if connection is active: ' + client.remoteAddress);
    if ( typeof (client.remoteAddress) == 'undefined' ) {
        client.connect( 2101, '10.10.10.4', function() {
            logger.info('Connection now open');
        });
    }
    else {
        logger.debug('Attempting reconnect on active connection. Ignore: ' + client.remoteAddress);
    }
};

// This events, as expected, when the VPN is connected and data is received.
client.on('data', function() {
    logger.debug('Data incoming');
});

// This events, as expected, when the VPN drops
client.on('error', function() {
    logger.debug('Connection error so destroy() the client');
    client.destroy();
    // I *was* expecting destroy() to make typeof (client.remoteAddress) = 'undefined'. It does not.
});

Here's what the resultant log looks like

info: Calling connect now...
debug: Test if connection is active: undefined
info: Connection now open
debug: Data incoming
debug: Data incoming

debug: Test if connection is active: 10.10.10.4
debug: Attempting reconnect on active connection. Ignore: 10.10.10.4
POST /elk/output 200 18.122 ms - 2

debug: Data incoming

I disconnected the VPN

debug: Test if connection is active: 10.10.10.4
debug: Attempting reconnect on active connection. Ignore: 10.10.10.4
POST /elk/output 200 1.546 ms - 2
debug: Connection error so destroy() the client

Now, given the client.destroy(); call, I'd expect client.remoteAddress to become undefined per document but it is not.

debug: Test if connection is active: 10.10.10.4
debug: Attempting reconnect on active connection. Ignore: 10.10.10.4
debug: Connection error so destroy() the client
POST /elk/output 200 1.063 ms - 2

Thoughts?

Thanks


Solution

  • You could also check if the TCP stream is readable or not by checking client.readable.