【问题标题】:Node http.request, no event(s) triggered if Internet stopped after sending the request节点 http.request,如果 Internet 在发送请求后停止,则不会触发任何事件
【发布时间】:2023-03-31 03:45:02
【问题描述】:

我在服务器上有以下 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);
});

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

重现问题:

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

我还发现如果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.

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

【问题讨论】:

  • 要重现,您也可以开始下载文件并拉动以太网电缆。我也有同样的问题。

标签: node.js http request client


【解决方案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

然后从节点脚本调用它并读取标准输出,例如使用 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】:

    对实际请求使用 setTimeout 可以解决您的问题。好吧,这不是像“关闭”、“结束”和“错误”这样的实际事件。下面的示例确实重现并解决了该问题,但尚未在其他情况下尝试过。

    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 中找到。要么使用它,要么也监听“关闭”事件,这与 net 模块配合得很好。

    【讨论】:

    • 纯节​​点和便携式解决方案,并没有真正深入阅读文档...谢谢^^
    【解决方案3】:

    这是我的解决方案......我不使用设置间隔,而是检查“数据”事件是否一直触发直到 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);
    }
    

    希望对你有帮助...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多