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

6voto

Ich hatte das gleiche Problem, als ich die Nano-Bibliothek verwendete, um eine Verbindung zu Couch DB herzustellen. Ich habe versucht, die Verbindungspooling mit der KeepAliveAgent-Bibliothek feinabzustimmen und es ist immer wieder mit der Meldung "Socket-Ausfall" fehlgeschlagen.

var KeepAliveAgent = require('agentkeepalive');

var myagent = new KeepAliveAgent({
    maxSockets: 10,
    maxKeepAliveRequests: 0,
    maxKeepAliveTime: 240000
});

nano = new Nano({
    url : uri,
    requestDefaults : {
        agent : myagent
    }
});

Nach einigem Hin und Her konnte ich das Problem lösen - es stellte sich heraus, dass es ein sehr einfacher Fehler war. Ich habe versucht, über das HTTPS-Protokoll eine Verbindung zur Datenbank herzustellen, aber ich habe meinem Nano-Objekt weiterhin einen KeepAlive-Agenten übergeben, der erstellt wurde, wie es die Beispiele für die Verwendung dieser Bibliothek zeigen (sie stützen sich auf einige Standardeinstellungen, die http verwenden).

Ein einfacher Wechsel zur Verwendung des HttpsAgent hat den Trick getan:

var KeepAliveAgent = require('agentkeepalive').HttpsAgent;

5voto

AndreyU Punkte 51

Ich hatte dasselbe Problem bei der Anfrage an einen Server. In meinem Fall hat es mir geholfen, einen Wert für User-Agent in den Kopfzeilen der Anfrageoptionen festzulegen.

const httpRequestOptions = {
    hostname: 'site.address.com',
    headers: {
       'User-Agent': 'Chrome/59.0.3071.115'
    }
};

Es handelt sich nicht um einen allgemeinen Fall und hängt von den Servereinstellungen ab.

4voto

Predrag Davidovic Punkte 841

Dieser Fehler kann auch auftreten, wenn Sie mit http.request arbeiten, wahrscheinlich ist Ihre Anfrage noch nicht abgeschlossen.

Beispiel:

const req = https.request(options, res => {})

Und Sie müssen immer diese Zeile hinzufügen: req.end() Mit dieser Funktion werden wir den Befehl zum Absenden der Anfrage geben.

Wie in der Dokumentation gesagt wird:

Bei http.request() muss man immer req.end() aufrufen, um das Ende der Anfrage anzuzeigen - auch wenn keine Daten in den Anfragekörper geschrieben werden.

3voto

Yehuda Punkte 979

Es ist schon lange her, aber ein weiterer Fall ist, wenn Anfragen durchgeführt werden, die auf der Serverseite lange dauern (mehr als 2 Minuten, was standardmäßig für Express gilt) und der Timeout-Parameter auf der Serverseite nicht konfiguriert wurde. In meinem Fall führte ich eine Client->Server->Server-Anfrage (Node.js Express) durch und ich musste den Timeout-Parameter auf jedem Anforderungs-Router auf dem Server und auf dem Client einstellen. Daher musste ich in beiden Servern den Anforderungs-Timeout einstellen, indem ich

req.setTimeout([your needed timeout])

auf dem Router verwendete.

3voto

Nikolay Podolnyy Punkte 732

Auch der Grund kann sein, dass stattdessen von const server = http.createServer(app) die app-Instanz von express anstelle von server verwendet wird, während der Server-Socket erstellt wird.

Falsch

const express = require('express');
const http = require('http');
const WebSocket = require('ws');

const app = express();

app.use(function (req, res) {
  res.send({ msg: "hello" });
});

const wss = new WebSocket.Server({ server: app }); // wird beim Verbinden vom Client-Socket einen Fehler werfen

app.listen(8080, function listening() {
  console.log('Listening on %d', server.address().port);
});

Richtig

const express = require('express');
const http = require('http');
const WebSocket = require('ws');

const app = express();

app.use(function (req, res) {
  res.send({ msg: "hello" });
});

const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

server.listen(8080, function listening() {
  console.log('Listening on %d', server.address().port);
});

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