Search code examples
javascriptandroidnode.jstelnet

Client connections not closed properly over retries


I have a small test telnet client, which needs to perform auth to android device. It works fine, However would like to understand if the approach seems correct & would not cause memory leaks.

The reason i feel that this script might cause memory leak is because when the connection is established on retires i see multiple confirmation of connection:

 node test.js
Connection refused, device not up yet..
Retrying..
Connection closed
CONNECTED TO: 127.0.0.1:5554
CONNECTED TO: 127.0.0.1:5554
Received: Android Console: Authentication required
Android Console: type 'auth <auth_token>' to authenticate
Android Console: you can find your <auth_token> in 
'/Users/testr/.emulator_console_auth_token'
OK

What i am expecting to see is only one instance of CONNECTED TO: 127.0.0.1:5554

I believe i am making a mistake somewhere to close the old connection but unable understand where.

If server is up:

in the first attempt, auth works fine:

CONNECTED TO: 127.0.0.1:5554
Received: Android Console: Authentication required
Android Console: type 'auth <auth_token>' to authenticate
Android Console: you can find your <auth_token> in 
'/Users/testr/.emulator_console_auth_token'
OK

On connection retry:

Connection refused, device not up yet..
Retrying..
Connection closed
CONNECTED TO: 127.0.0.1:5554
CONNECTED TO: 127.0.0.1:5554
Received: Android Console: Authentication required
Android Console: type 'auth <auth_token>' to authenticate
Android Console: you can find your <auth_token> in 
'/Users/testr/.emulator_console_auth_token'
OK

const net = require('net');
const HOST = '127.0.0.1';
const Port = 5554;
let client = new net.Socket();


    // connection
     const conn = function Connect(Port) {
         client.connect(Port, '127.0.0.1', function () {
            console.log('CONNECTED TO: ' + '127.0.0.1' + ':' + Port);
             client.write('auth testcred');
        });
    };

     // error handling
    client.on('error', function (error) {
        if (error.code === 'ECONNREFUSED') {
            console.log("Connection refused, device not up yet..");
            console.log("Retrying..");
            setTimeout(function() {
                conn(Port);
            }, 10000);
        }
    });

    // on response from server
    client.on('data', function(data) {
        console.log('Received: ' + data);
        client.destroy();
        client.removeAllListeners();
    });

    // on connection closure
    client.on('close', function() {
        console.log('Connection closed');
        client.destroy();
    });


     conn(Port);


I expect the output to just return CONNECTED TO: 127.0.0.1:5554 only once but i see it getting printed equal to amount of retries.


Solution

  • What's probably happening is:

    1. You only have one socket, and:
    2. It's only experiencing one connection at a time, but:
    3. You've got multiple connectListeners registered on the socket. A new one is being registered each time you call connect(), and the list just keeps getting longer and longer.

    Ref. the docs:

    connectListener Common parameter of socket.connect() methods. Will be added as a listener for the 'connect' event once.

    The advice the doc gives (to open the Socket with net.createConnection()) might be appropriate, in this case. Instead of giving client a long lifetime, you'd be better off replacing it each time you want to start a new connection.