为了账号安全,请及时绑定邮箱和手机立即绑定

NodeJS-“套接字挂起”实际上是什么意思?

NodeJS-“套接字挂起”实际上是什么意思?

饮歌长啸 2019-12-10 10:58:42
我正在使用Node和Cheerio构建网络抓取工具,对于某个网站,我遇到以下错误(它仅在该网站上发生,没有其他我尝试抓取的错误。每次都在不同的位置发生,所以有时url x是引发错误,有时url x是,并且完全是另一个URL:    Error!: Error: socket hang up using [insert random URL, it's different every time]Error: socket hang up    at createHangUpError (http.js:1445:15)    at Socket.socketOnEnd [as onend] (http.js:1541:23)    at Socket.g (events.js:175:14)    at Socket.EventEmitter.emit (events.js:117:20)    at _stream_readable.js:910:16    at process._tickCallback (node.js:415:13)调试起来非常棘手,我真的不知道从哪里开始。首先,什么是套接字挂起错误?是404错误还是类似错误?还是仅表示服务器拒绝连接?我在任何地方都找不到这种解释!编辑:这是(有时)返回错误的代码示例:function scrapeNexts(url, oncomplete) {    request(url, function(err, resp, body) {        if (err) {            console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);            errors.nexts.push(url);        }        $ = cheerio.load(body);        // do stuff with the '$' cheerio content here    });}没有直接调用来关闭连接,但是我正在使用Node Request(据我所知)使用的连接,http.get因此这不是必需的,如果我错了,请纠正我!编辑2:这是导致错误的实际使用中的代码。prodURL其他变量主要是前面定义的jquery选择器。这将async库用于Node。function scrapeNexts(url, oncomplete) {    request(url, function (err, resp, body) {        if (err) {            console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);            errors.nexts.push(url);        }        async.series([                function (callback) {                    $ = cheerio.load(body);                    callback();                },                function (callback) {                    $(prodURL).each(function () {                        var theHref = $(this).attr('href');                        urls.push(baseURL + theHref);                    });                    var next = $(next_select).first().attr('href');                    oncomplete(next);                }            ]);    });}
查看完整描述

3 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

有两种情况socket hang up会被抛出:


当您是客户时

当您作为客户端时,将请求发送到远程服务器,并且不会及时收到响应。您的套接字已结束,将引发此错误。您应该捕获此错误并决定如何处理:是否重试该请求,将其排队以备后用,等等。


当您是服务器/代理

当您作为服务器(也许是代理服务器)从客户端接收请求,然后开始对其执行操作(或将请求中继到上游服务器)时,在准备响应之前,客户端决定取消/中止操作请求。


此堆栈跟踪显示了客户端取消请求时发生的情况。


Trace: { [Error: socket hang up] code: 'ECONNRESET' }

    at ClientRequest.proxyError (your_server_code_error_handler.js:137:15)

    at ClientRequest.emit (events.js:117:20)

    at Socket.socketCloseListener (http.js:1526:9)

    at Socket.emit (events.js:95:17)

    at TCP.close (net.js:465:12)

行http.js:1526:9指向socketCloseListener@Blender上面提到的内容,尤其是:


// This socket error fired before we started to

// receive a response. The error needs to

// fire on the request.

req.emit('error', createHangUpError());


...


function createHangUpError() {

  var error = new Error('socket hang up');

  error.code = 'ECONNRESET';

  return error;

}

如果客户端是浏览器中的用户,这是一种典型情况。加载某些资源/页面的请求需要很长时间,并且用户只需刷新页面即可。这样的操作会使先前的请求中止,从而在服务器端抛出此错误。


由于此错误是由客户的意愿引起的,因此他们不希望收到任何错误消息。因此,无需将此错误视为严重错误。只是忽略它。由于这样的事实,这鼓励了res您的客户端侦听的套接字,尽管该套接字仍可写,但仍可写。


console.log(res.socket.destroyed); //true

因此,除了显式关闭响应对象之外,没有任何发送任何内容的方法:


res.end();

但是,如果您是已经将请求中继到上游的代理服务器,您应该确定要中止内部请求到上游,这表明您对响应不感兴趣,这反过来会告诉上游服务器也许停止了昂贵的操作。


查看完整回答
反对 回复 2019-12-10
?
UYOU

TA贡献1878条经验 获得超4个赞

看一下来源:


function socketCloseListener() {

  var socket = this;

  var parser = socket.parser;

  var req = socket._httpMessage;

  debug('HTTP socket close');

  req.emit('close');

  if (req.res && req.res.readable) {

    // Socket closed before we emitted 'end' below.

    req.res.emit('aborted');

    var res = req.res;

    res.on('end', function() {

      res.emit('close');

    });

    res.push(null);

  } else if (!req.res && !req._hadError) {

    // This socket error fired before we started to

    // receive a response. The error needs to

    // fire on the request.

    req.emit('error', createHangUpError());

    req._hadError = true;

  }

}

服务器从不发送响应时,将发出此消息。


查看完整回答
反对 回复 2019-12-10
  • 3 回答
  • 0 关注
  • 635 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信