Node http.request, no event(s) triggered if Intern

2019-05-17 15:22发布

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.

2条回答
放荡不羁爱自由
2楼-- · 2019-05-17 15:53

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.

查看更多
甜甜的少女心
3楼-- · 2019-05-17 15:57

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);
查看更多
登录 后发表回答