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

我正在使用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);

                }

            ]);

    });

}


慕桂英4014372
浏览 573回答 3
3回答

胡子哥哥

有两种情况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();但是,如果您是已经将请求中继到上游的代理服务器,您应该确定要中止内部请求到上游,这表明您对响应不感兴趣,这反过来会告诉上游服务器也许停止了昂贵的操作。

12345678_0001

看一下来源: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;  }}服务器从不发送响应时,将发出此消息。分享编辑
打开App,查看更多内容
随时随地看视频慕课网APP