节点http.request,如果在发送请求后Internet停止,则不会触发任何事件

时间:2014-03-13 18:02:15

标签: node.js http request client

我在服务器上有以下PHP脚本,它将等待10秒并说出Hello

<php sleep(10); ?>Hello

在客户端(节点),我有以下内容:

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);
});

问题是,如果在请求期间互联网连接停止,它将不会触发errorend个事件。

重新产生问题:

  • 将PHP脚本放在互联网上的某个地方
  • 执行节点脚本
  • 断开互联网
  • 脚本什么都不做

我还发现,如果连接在10秒内恢复,它仍然可以收到消息。

所以,我做了一个简单的间隔循环来检查状态。但是,它无法检测连接是否已停止工作或仍在等待响应:

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.

所以我的问题是:有没有办法在发送请求后检查套接字是否已关闭/连接? 提前谢谢。

3 个答案:

答案 0 :(得分:3)

在实际请求中使用setTimeout可以解决您的问题。嗯,这不是一个真实的事件,比如&#39; close&#39;,&#39; end&#39;并且&#39;错误&#39;。下面的示例确实可以复制并解决问题,但并未尝试在其他环境中使用它。

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);
});        

可以在documentation中找到更多信息。要么使用它,要么倾听&#39;关闭&#39;事件也适用于网络模块。

答案 1 :(得分:1)

也许这对你有用:

创建一个bash脚本来检查连接(从https://stackoverflow.com/a/14939373/1779015抓取一点点修改):

    #!/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

然后从节点脚本调用它并读取stdout,例如使用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);

答案 2 :(得分:0)

这是我的解决方案...我没有使用设置间隔,而是检查“数据”事件是否一直触发直到END事件。


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);
}

希望这对您有帮助...