Reconnect net.socket nodejs

I am new to node.js and would like to connect to a TCP socket. For this I am using a network module.

My idea was to wrap the connection sequence in a function and then in a "close" event to try to reconnect. Not so easy.

function conn() {

    client.connect(HOST_PORT, HOST_IP, function() {
        startSequence();
    })
}

client.on('close', function(e) {
    log('info','Connection closed! -> ' + e)
    client.destroy();
    setTimeout(conn(),1000);
});

      

So when the remote host is shut down, I see my logs going, however, what seems to be going on is that as the remote host comes online, all previous attempts start being processed - if that makes sense. If you look at client.connect, there is a function called startSequence that sends some data that preempts the connection from the remote server side. When the server goes offline and I start reconnecting all the failed attempts before they seem to have been buffered, and they are all sent together when the server goes online.

I tried the code from this Stackoverflow link but to no avail ( Nodejs - getting client socket to retry after 5 seconds of inactivity )

client.connect(HOST_PORT, HOST_IP, function() {
    pmsStartSequence();
})


// Add a 'close' event handler for the client socket
client.on('close', function(e) {
    log('debug','connection  closed -> ' + e)
    client.setTimeout(10000, function() {
        log('debug', 'trying to reconnect')
        client.connect(HOST_PORT, HOST_IP, function() {
            pmsStartSequence();
        })
    })
});

      

Is there any advice on how I can reconnect the socket after a failure?

+6


source to share


8 answers


The problem is that you are setting a callback on connect.

The socket.connect () doc says:

connectListener ... will be added as a listener for the connect event once.



By setting it in calls to socket.connect (), every time you try to reestablish a connection, another listener (one-time) is attached to that socket, which calls startSequence (). These listeners will not be fired until after a successful reconnection occurs, so they will all be activated at the same time on the same connection.

One possible solution is to decouple the connection listener from the socket.connect () calls.

client.on('connect', function() {
    pmsStartSequence();
});

client.on('close', function(e) {
    client.setTimeout(10000, function() {
        client.connect(HOST_PORT, HOST_IP);
    })
});

client.connect(HOST_PORT, HOST_IP);

      

+8


source


My decision:

var parentHOST = '192.168.2.66';
var parentPORT = 9735;

var net = require('net');
var S = require('string');
var parentClient = new net.Socket();
var parentActive = false;

var startParentClient = function () {
    parentClient = new net.Socket();
    parentActive = false;

    parentClient.connect(parentPORT, parentHOST, function() {
      console.log('Connected ' + cluster.worker.id + ' to parent server: ' + parentHOST + ':' + parentPORT);
      parentActive = true;
    });

    parentClient.on('error', function() {
      parentActive = false;
      console.log('Parent connection error');
    });

    parentClient.on('close', function() {
      parentActive = false;
      console.log('parent connection closed');
      setTimeout(startParentClient(), 4000);
    });
  }

      



If necessary connect:

  if (!S(parentHOST).isEmpty() && !S(parentPORT).isEmpty()) {
    startParentClient();
  }

      

+4


source


Inspired by other solutions, I wrote this, tested it, it works! It will keep trying every 5 seconds until the connection is done, works if it also loses the connection.

/* Client connection */
/* --------------------------------------------------------------------------------- */

const client = new net.Socket()
var intervalConnect = false;

function connect() {
    client.connect({
        port: 1338,
        host: '127.0.0.1'
    })
}

function launchIntervalConnect() {
    if(false != intervalConnect) return
    intervalConnect = setInterval(connect, 5000)
}

function clearIntervalConnect() {
    if(false == intervalConnect) return
    clearInterval(intervalConnect)
    intervalConnect = false
}

client.on('connect', () => {
    clearIntervalConnect()
    logger('connected to server', 'TCP')
    client.write('CLIENT connected');
})

client.on('error', (err) => {
    logger(err.code, 'TCP ERROR')
    launchIntervalConnect()
})
client.on('close', launchIntervalConnect)
client.on('end', launchIntervalConnect)

connect()

      

+3


source


I am using the following code to reconnect using node.js. I'm not a Javascript expert, so I think it can be improved, but it still works great for me. Hope this helps. Best.

//----------------------------------------------------------------//
// SocketClient                                                   //
//----------------------------------------------------------------//
var net = require('net');

var SocketClient = function(host, port, data_handler, attempt)
{
    var node_client;
    var attempt_index = (attempt ? attempt : 1);

    this.m_node_client = new net.Socket();
    node_client = this.m_node_client;
    this.m_node_client.on('close', function()
    {
        var new_wrapper = new SocketClient(host, port, data_handler, attempt_index + 1);

        node_client.destroy();
        new_wrapper.start();
    });
    this.m_node_client.on('data', data_handler);
    this.m_node_client.on('error', function(data)
    {
        console.log("Error");
    });
    this.start = function()
    {
        this.m_node_client.connect(port, host, function()
        {
            console.log('Connected ' + attempt_index);
        });
    };
};

//----------------------------------------------------------------//
// Test                                                           //
//----------------------------------------------------------------//
var test_handler = function(data)
{
    console.log('TestHandler[' + data + ']');
};
var wrapper = new SocketClient('127.0.0.1', 4000, test_handler);

wrapper.start();

      

+1


source


As mentioned many times in the comments, you need to use .removeAllListeners()

before trying to reconnect the client to the server to avoid multiple listeners listening for the same event at the same time.

The code below should work

Please note that I am trying to reconnect the client after the events close

and end

because the two events can be fired in different orders after the connection is closed

const net = require("net")

let client = new net.Socket()

function connect() {
    console.log("new client")
    client.connect(
        1337,
        "127.0.0.1",
        () => {
            console.log("Connected")
            client.write("Hello, server! Love, Client.")
        }
    )

    client.on("data", data => {
        console.log("Received: " + data)
    })

    client.on("close", () => {
        console.log("Connection closed")
        reconnect()
    })

    client.on("end", () => {
        console.log("Connection ended")
        reconnect()
    })

    client.on("error", console.error)
}

// function that reconnect the client to the server
reconnect = () => {
    setTimeout(() => {
        client.removeAllListeners() // the important line that enables you to reopen a connection
        connect()
    }, 1000)
}

connect()

      

+1


source


I tried to reuse the same socket connection using this:

const s = net.createConnection({port});

s.once('end', () => {
    s.connect({port}, () => {

    });
});

      

it didn't work, from the server's point of view. If the client connection is closed, it is recommended to create a new connection:

const s = net.createConnection({port});

s.once('end', () => {
    // create a new connection here
    s = net.createConnection(...);
});

      

sad but real lulz.

0


source


After that :

//
// Simple example of using net.Socket but here we capture the
// right events and attempt to re-establish the connection when
// is is closed either because of an error establishing a
// connection or when the server closes the connection.
//

// Requires
const net = require('net');

// Create socket
const port = 5555;
const host = '127.0.0.1';
const timeout = 1000;
let retrying = false;

// Functions to handle socket events
function makeConnection () {
    socket.connect(port, host);
}
function connectEventHandler() {
    console.log('connected');
    retrying = false;
}
function dataEventHandler() {
    console.log('data');
}
function endEventHandler() {
    // console.log('end');
}
function timeoutEventHandler() {
    // console.log('timeout');
}
function drainEventHandler() {
    // console.log('drain');
}
function errorEventHandler() {
    // console.log('error');
}
function closeEventHandler () {
    // console.log('close');
    if (!retrying) {
        retrying = true;
        console.log('Reconnecting...');
    }
    setTimeout(makeConnection, timeout);
}

// Create socket and bind callbacks
let socket = new net.Socket();
socket.on('connect', connectEventHandler);
socket.on('data',    dataEventHandler);
socket.on('end',     endEventHandler);
socket.on('timeout', timeoutEventHandler);
socket.on('drain',   drainEventHandler);
socket.on('error',   errorEventHandler);
socket.on('close',   closeEventHandler);

// Connect
console.log('Connecting to ' + host + ':' + port + '...');
makeConnection();

      

0


source


function createServer() {
  const client = new net.Socket();

  client.connect(HOST_PORT, HOST_IP, function() {
    console.log("Connected");
    state = 1 - state;
    client.write(state.toString());
  });

  client.on("data", function(data) {
    console.log("Received: " + data);
    //client.destroy(); // kill client after server response
  });

  client.on("close", function() {
    console.log("Connection closed");
    //client.connect()
    setTimeout(createServer, 2000);
  });
}

createServer();

      

0


source







All Articles