5

I have the following PHP Script on server that will wait 10 seconds and say Hello:

<php sleep(10); ?>Hello

On the client side (node), I have the following:

var http = require('http');
http.get ('http://example.com/sleep.php', function (resp) {
    resp.on('data', function (d) {
        console.log ('data!', d.toString());
    });
    resp.on('end', function (d) {
        console.log ('Finished!');
    });
}).on('error', function (e) {
    console.log ('error:', e);
});

The problem is, if the internet connection stopped during the request, it will not trigger error OR end events.

To re-produce the problem:

  • Place the PHP script somewhere on the Internet
  • Execute the node script
  • Disconnect the Internet
  • The script does nothing

I've also found that if the connection is back within 10 seconds, it can still receive the message.

So, I made a simple interval loop to check the status. However it can't detect if the connection has stopped working or still waiting for response:

var http = require('http');
var lastRespond = 0, intervalCheck;
var respFinished = false;
http.get ('http://jixun.no-ip.org/sleep.php', function (resp) {
    resp.on('data', function (d) {
        lastRespond = new Date;
        console.log ('data!', d.toString());
    });
    resp.on('end', function (d) {
        respFinished = true;
        console.log ('Finished!');
    });
}).on('error', function (e) {
    console.log ('error:', e);
});
intervalCheck = setInterval(function () {
    if (respFinished) {
        clearInterval(intervalCheck);
    } else if (new Date - lastRespond >= 120000) {
        console.log ('Timeout   :(');
        clearInterval(intervalCheck);
    }
}, 120000); // 2 mins.

So my question is: Is there any way to check if the socket closed / connection stopped after sending the request? Thanks in advance.

Philip Allgaier
  • 3,505
  • 2
  • 26
  • 53
Jixun
  • 140
  • 10
  • To reproduce, you can also start to download a file and pull the ethernet cable. I m having the same problem. – DrakaSAN Apr 10 '14 at 12:41

3 Answers3

3

Using setTimeout on the actual request could solve your problem. Well, it's not an actual event like 'close', 'end' and 'error'. Sample below does reproduce and solves the issue, haven't tried it in another context though.

var http = require('http'); 
http.get ('http://fake-response.appspot.com?sleep=5', function (resp) { 
  resp.on('data', function (d) {
    console.log ('data!', d.toString()); 
  }); 
  resp.on('end', function (d) { 
     console.log ('Finished!'); 
  }); 
}).on('error', function (e) {
    console.log ('error:', e); 
}).setTimeout(12000, function ( ) { 
    console.log('Timeout reached...'); 
    process.exit(1);
});        

More information can be found in the documentation. Either use that or listening on the 'close' event as well, that works well with the net module.

fresla
  • 250
  • 2
  • 8
  • 1
    Pure node and portable solution, didn't really read deep to the documentation... Thanks ^^ – Jixun Apr 14 '14 at 19:01
1

Maybe this would be usefull for you:

Create a bash script which checks connection (grabbed from https://stackoverflow.com/a/14939373/1779015 with little modifications):

    #!/bin/bash

    # Test for network conection
    for interface in $(ls /sys/class/net/ | grep -v lo);
    do
        if [[ $(cat /sys/class/net/$interface/carrier 2> /dev/null) = 1 ]]; then  OnLine=1; fi
    done
    if ! [ $OnLine ]; then echo "0";
    else 
        echo "1";
    fi

Then call it from node script and read stdout, for example with child_process (http://nodejs.org/api/child_process.html):

var spawn = require('child_process').spawn,
    hasInet  = spawn('./test-inet.sh');

hasInet.stdout.pipe(process.stdout);
Community
  • 1
  • 1
zarkone
  • 1,335
  • 10
  • 16
1

Here is my solution ... instead of using set interval I check if on "data" event keeps firing until END event.


var http = require('http'); 
var url = require('url'); 

var options = {};
var parsed_url = url.parse(url, true);
var req_options = {
  path: parsed_url.pathname,
  host: parsed_url.hostname
};

var file = fs.createWriteStream(filename,options);
try{
  const check_data_timeout = 10000;
  var check_data_timer = 0;
  var current_size = 0;
  var request = http.get(req_options, function(response) {
      len = parseInt(response.headers['content-length'], 10);
      response.on("data", function(chunk) {
              current_size += chunk.length;
              percent = (100.0 * current_size / len).toFixed(2);
              console.log("Download percent : "+percent+"%");
              clearTimeout(check_data_timer);
              check_data_timer = setTimeout(function(){
                console.log("UPS !! No new data ... connection must be stalled");
              },check_data_timeout);
      });
      response.on("end", function() {
        console.log("Response ENDED !!!");
        clearTimeout(check_data_timer);
      });
      response.pipe(file);
      check_data_timer = setTimeout(function(){
        console.log("UPS !! No new data ... connection must be stalled");
      },check_data_timeout);
  }).once('error', function(error) {
     console.log("Response ERROR !!!");
  });
}catch(e){
  console.log(e);
}

Hope it helps ...