[node.js] 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 선택기입니다. asyncNode 용 라이브러리를 사용합니다 .

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



답변

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)

라인 은 @Blender가 위에서 언급 한 http.js:1526:9것과 동일하게 지적합니다 socketCloseListener.

// 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();

그러나, 당신이 무엇을 해야 당신이 경우에 확실 하다 이미 상류에 요청을 전달했다 프록시 서버, 다시 상류을 말할 것이다 응답에서 관심의 부족을 나타내는 상류에 내부 요청을 중단하는 것입니다 아마도 비싼 작업을 중지하기 위해 서버.


답변

소스를 살펴보십시오 .

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

서버가 응답을 보내지 않으면 메시지가 생성됩니다.


답변

언급 할 가치가있는 한 가지 사례 : Express를 사용하여 Node.js에서 Node.js로 연결할 때 요청 된 URL 경로 앞에 “/”를 붙이지 않으면 “소켓 끊기”가 발생합니다.


답변

내가 사용하는 require('http')소비 HTTPS 서비스를하며 “보여 주었다 socket hang up“.

그런 다음 대신에 변경 require('http')되어 require('https')작동합니다.


답변

아래는 아래 예제에서 주석이 달린 코드를 추가하지 못했을 때 동일한 오류가 발생하는 간단한 예입니다. 코드 주석 처리를 제거하면 req.end()이 문제가 해결됩니다.

var fs = require("fs");
var https = require("https");

var options = {
    host: "en.wikipedia.org",
    path: "/wiki/George_Washington",
    port: 443,
    method: "GET"
};

var req = https.request(options, function (res) {
    console.log(res.statusCode);
});


// req.end();


답변

블렌더의 답변을 확장하면 여러 상황에서 발생합니다. 내가 만나는 가장 일반적인 것은 다음과 같습니다.

  1. 서버가 충돌했습니다.
  2. 서버가 귀하의 연결을 거부했습니다 User-Agent.

socketCloseListener블렌더의 답변에 요약 된 것처럼 끊기 오류가 생성되는 유일한 장소는 아닙니다.

예를 들어, 여기에 있습니다 :

function socketOnEnd() {
  var socket = this;
  var req = this._httpMessage;
  var parser = this.parser;

  if (!req.res) {
    // If we don't have a response then we know that the socket
    // ended prematurely and we need to emit an error on the request.
    req.emit('error', createHangUpError());
    req._hadError = true;
  }
  if (parser) {
    parser.finish();
    freeParser(parser, req);
  }
  socket.destroy();
}

당신은 시도 할 수 curl헤더와 함께 노드에서 발송하고 당신이 응답을 얻을 수 있는지 확인하고되도록. 로 응답이 curl없지만 브라우저에서 응답을 받으면 User-Agent헤더가 차단되었을 가능성이 큽니다.


답변

언급 할 가치가있는 또 다른 경우 (Linux 및 OS X의 경우)는 https요청 수행 과 같은 라이브러리를 사용 하거나 https://...로컬로 제공되는 인스턴스의 URL로 전달 443하면 예약 된 개인 포트 인 포트를 사용하고 끝나 Socket hang up거나 ECONNREFUSED오류가 발생 했을 수 있습니다 .

대신 port 3000, fe를 사용 하고 http요청하십시오.