435 Stimmen

NodeJS - Was bedeutet "socket hang up" eigentlich?

Ich baue einen Web-Scraper mit Node und Cheerio, und für eine bestimmte Website erhalte ich den folgenden Fehler (es tritt nur auf dieser einen Website auf, bei keiner anderen, die ich zu scrapen versuche).

Es passiert jedes Mal an einem anderen Ort, also manchmal ist es url x, der den Fehler wirft, andere Male ist url x in Ordnung und es handelt sich um eine völlig andere URL:

    Fehler!: Fehler: Socket wurde geschlossen using [zufällige URL einfügen, es ist jedes Mal eine andere]

Fehler: Socket wurde geschlossen
    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)

Das ist sehr schwierig zu debuggen, ich weiß nicht wirklich, wo ich anfangen soll. Um zu beginnen, was IST ein Verbindungsabbruchfehler (Socket hang up error)? Ist es ein 404-Fehler oder ähnliches? Oder bedeutet es einfach, dass der Server eine Verbindung verweigert hat?

Ich kann keine Erklärung dafür finden!

BEARBEITEN: Hier ist ein Codebeispiel, der (manchmal) Fehler zurückgibt:

function scrapeNexts(url, oncomplete) {
    request(url, function(err, resp, body) {

        if (err) {
            console.log("Ach, ScrapeNexts Fehler!: " + err + " beim Verwenden von " + url);
            errors.nexts.push(url);
        }
        $ = cheerio.load(body);
        // hier wird etwas mit dem '$' Cheerio-Inhalt gemacht
    });
}

Es erfolgt kein direkter Aufruf, um die Verbindung zu schließen, aber ich verwende Node Request, das (soweit ich das beurteilen kann) http.get verwendet, sodass dies nicht erforderlich ist. Bitte korrigiere mich, wenn ich falsch liege!

BEARBEITEN 2: Hier ist ein tatsächliches, im Einsatz befindliches Code-Snippet, das Fehler verursacht. prodURL und andere Variablen sind größtenteils vorher definierte jQuery-Selektoren. Hier wird die async-Bibliothek für Node verwendet.

function scrapeNexts(url, oncomplete) {
    request(url, function (err, resp, body) {

        if (err) {
            console.log("Ach, ScrapeNexts Fehler!: " + err + " beim Verwenden von " + 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);
                }
            ]);
    });
}

24voto

Sly Punkte 1145

Erweiternd zu Blender's Antwort, passiert dies in einer Reihe von Situationen. Die häufigsten, auf die ich stoße, sind:

  1. Der Server ist abgestürzt.
  2. Der Server hat Ihre Verbindung abgelehnt, höchstwahrscheinlich blockiert durch User-Agent.

socketCloseListener, wie in Blender's Antwort dargelegt, ist nicht der einzige Ort, an dem Aufhängefehler erstellt werden.

Zum Beispiel hier gefunden hier:

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

  if (!req.res) {
    // Wenn wir keine Antwort haben, dann wissen wir, dass der Socket
    // vorzeitig beendet wurde und wir einen Fehler auf der Anforderung auslösen müssen.
    req.emit('error', createHangUpError());
    req._hadError = true;
  }
  if (parser) {
    parser.finish();
    freeParser(parser, req);
  }
  socket.destroy();
}

Sie könnten versuchen, curl mit den Headern und Ähnlichem auszuprobieren, die von Node gesendet werden, und sehen, ob Sie dort eine Antwort erhalten. Wenn Sie mit curl keine Antwort erhalten, aber in Ihrem Browser eine erhalten, dann wird höchstwahrscheinlich Ihr User-Agent-Header blockiert.

8voto

Für Benutzer des request Moduls

Timeouts

Es gibt zwei Hauptarten von Timeouts: Verbindungs-Timeouts und Lese-Timeouts. Ein Verbindungs-Timeout tritt auf, wenn das Timeout erreicht wird, während Ihr Client versucht, eine Verbindung zu einer entfernten Maschine herzustellen (entsprechend dem connect() Aufruf auf dem Socket). Ein Lese-Timeout tritt auf, wenn der Server zu langsam ist, um einen Teil der Antwort zurückzusenden.

Beachten Sie, dass Verbindungs-Timeouts einen ETIMEDOUT Fehler auslösen und Lese-Timeouts einen ECONNRESET Fehler auslösen.

8voto

Milkncookiez Punkte 5833

Ein weiterer erwähnenswerter Fall (für Linux und OS X) ist, dass wenn Sie eine Bibliothek wie https für die Durchführung der Anfragen verwenden oder wenn Sie https://... als URL der lokal bereitgestellten Instanz übergeben, werden Sie den Port 443 verwenden, der ein reservierter privater Port ist und Sie könnten auf Socket hang up oder ECONNREFUSED Fehler stoßen.

Verwenden Sie stattdessen den Port 3000 und führen Sie eine http Anfrage durch.

7voto

Jeffrey Harmon Punkte 2018

Dies verursachte Probleme bei mir, da ich alles aufgelistete hier gemacht habe, aber trotzdem Fehlermeldungen erhalten habe. Es stellte sich heraus, dass ein Aufruf von req.abort() tatsächlich einen Fehler wirft, mit einem Code von ECONNRESET, also musst du das tatsächlich in deinem Fehlerhandler abfangen.

req.on('error', function(err) {
    if (err.code === "ECONNRESET") {
        console.log("Timeout tritt auf");
        return;
    }
    // Normale Fehler behandeln
});

7voto

Eric McLachlan Punkte 2378

Ich denke, dass "Socket-Aufhängung" ein ziemlich allgemeiner Fehler ist, der darauf hinweist, dass die Verbindung vom Serverende beendet wurde. Mit anderen Worten, die Sockets, die zur Aufrechterhaltung der Verbindung zwischen Client und Server verwendet werden, wurden getrennt. (Obwohl ich sicher bin, dass viele der oben genannten Punkte für verschiedene Personen hilfreich sind, denke ich, dass dies die allgemeinere Antwort ist.)

In meinem Fall habe ich eine Anfrage mit einer Nutzlast von mehr als 20K gesendet. Dies wurde vom Server abgelehnt. Ich habe dies überprüft, indem ich Text entfernt und es erneut versucht habe, bis die Anfrage erfolgreich war. Nach Bestimmung der maximal akzeptablen Länge habe ich festgestellt, dass das Hinzufügen eines einzelnen Zeichens den Fehler auftreten ließ. Ich habe auch bestätigt, dass der Client nicht das Problem war, indem ich die gleiche Anfrage von einer Python-App und von Postman aus gesendet habe. Also bin ich zuversichtlich, dass in meinem Fall die Länge der Nutzlast mein spezifisches Problem war.

Nochmals, die Quelle des Problems ist anekdotisch. Das allgemeine Problem ist "Server sagt Nein".

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X