2

I can't figure out one problem I got. I'm using the Net module on my Node.JS server which is used to listen to client connections.

The client do connect to the server correctly and the connection remains available to read/write data. So far, so good. But when the client unexpectedly disconnects (ed. when internet falls away at client side) I want to fire an event server side.

In socket.io it would be done with the 'disconnect' event, but this event doesn't seem to exist for the Net module. How is it possible to do?

I've searched on Google/StackOverflow and in the Net documentation (https://nodejs.org/api/net.html) but I couldn't find anything usefull. I'm sry if I did mis something.

Here is a code snippet I got:

var net = require('net');

var server = net.createServer(function(connection) {
    console.log('client connected');
    connection.wildcard = false;//Connection must be initialised with a configuration stored in the database
    connection.bidirectional = true;//When piped this connection will be configured as bidirectional

    connection.setKeepAlive(true, 500);
    connection.setTimeout(3000);

    connection.on('close', function (){
        console.log('Socket is closed');
     });

    connection.on('error', function (err) {
        console.log('An error happened in connection' + err.stack);
    });
    connection.on('end', function () {
        console.log('Socket did disconnect');
    });
    connection.on('timeout', function () {
        console.log('Socket did timeout');
        connection.end();
    });
    connection.on('data', function (data) {
        //Handling incoming data
    });

});

serverUmrs.listen(40000, function () {
    console.log('server is listening');
});

All the events(close, end, error, timeout) don't fire when I disconnect the client(by pulling out the UTP cable).

Thanks in advance!

EDIT: I did add a timeout event in the code here above but the only thing that happens is that the socket does timeout after 3 seconds everytime the client does connect again. Isn't KeepAlive enough to make the socket not Idle? How is it possible to make the socket not idle without to much overhead. It may be possible that there are more than 10,000 connections at the same time which must remain alive as long as they are connected (ie respond to the keepalive message).

Sander
  • 171
  • 1
  • 10

2 Answers2

2

Update:

I think the KeepAlive is not related with the Idle state of socket, sort of.

Here is my test, I remove the following code in your example.

//connection.setKeepAlive(true, 500);

Then test this server with one client connect to it var nc localhost 40000. If there is no message sending to server after 3 seconds, the server logs as below

Socket did timeout
Socket did disconnect
Socket is closed

The timeout event is triggered without KeepAlive setting.

Do further investigation, refer to the Node.js code

function onread(nread, buffer) {
  //...
  self._unrefTimer();

We know timeout event is triggered by onread() operation of socket. Namely, if there is no read operation after 3 seconds, the timeout event will be emitted. To be more precisely, not only onread but also write successfully will call _unrefTimer().

In summary, when the write or read operation on the socket, it is NOT idle.


Actually, the close event is used to detect the client connection is alive or not, also mentioned in this SO question.

Emitted when the server closes. Note that if connections exist, this event is not emitted until all connections are ended.

However, in your case

disconnect the client(by pulling out the UTP cable).

The timeout event should be used to detective the connection inactivity. This is only to notify that the socket has been idle. The user must manually close the connection. Please refer to this question.

Community
  • 1
  • 1
zangw
  • 43,869
  • 19
  • 177
  • 214
  • Thanks but I don't get the functionality to work with use of the timeout event. See the Edit and changed code snippet in my question post for more information. – Sander Jan 11 '16 at 18:04
  • @Sander, my answer is updated, hope it can help you. – zangw Jan 12 '16 at 10:08
0

In TCP connection, end event fire when the client sends 'FIN' message to the server.

If the client side is not sending 'FIN' message that event is not firing.

For example, in your situation,

But when the client unexpectedly disconnects (ed. when internet falls away at client side) I want to fire an event server side.

There may not be a 'FIN' message because internet is gone.

So you should handle this situation in timeout without using keepAlive. If there is no data coming data, you should end or destroy the socket.

EDIT: I did add a timeout event in the code here above but the only thing that happens is that the socket does timeout after 3 seconds everytime the client does connect again. Isn't KeepAlive enough to make the socket not Idle? How is it possible to make the socket not idle without to much overhead. It may be possible that there are more than 10,000 connections at the same time which must remain alive as long as they are connected (ie respond to the keepalive message).

For your edit, your devices should send to the server some heartbeat message between a time period. So that, server understands that that device is alive and that timeout event will not fire because you get some data. If there is no heartbeat message such cases you cannot handle this problem.

Alexander Chef
  • 378
  • 1
  • 2
  • 13