JavaScript EventSource und NodeJS - beenden der verbinung bemerken

mercsen

Lt. Commander
Registriert
Apr. 2010
Beiträge
1.680
Moin moin liebe CB Gemeinde,

wiedermal melde ich mich mit einem Problem betreffend SSE.

Auf meiner Seite gibt es eine EventSource die sich mit einem NodeJS server verbindet.

meine frage ist nun wie ich mitbekommen wenn der client (also die seite) die verbindung wieder schließt.

ich habe mittlerweile so ziemlich alles versucht:

ich lasse zum test im 3 sekunden takt eine nachricht an den clienten schicken, in der erwartung das bei beendeter verbinung irgendein error event getriggert wird, aber pustekuchen!

weder das binden der events "close", "error" und "end" an den socket, noch die events
"close", "end", "clientError", "error" an das Response und oder das Request object feuern im richtigen Moment!

der server sendet munter weiter seine dump packete (die ja nur gucken sollen ob die verbinung noch offen ist) ohne einen fehler zu erzeugen und dann irgendwann, mal nach 10- mal nach 50 sekunden feuern so ziemlich alle Handler auf einmal. Das kann doch nicht richtig sein?

Auf client seite ist die EventSource im Status 2 (also verbindung zu und keine reconnects), nur wieso kann ich das nicht auf dem Node Server mitbekommen?

sendet die EventSource keinen end befehl wenn man die close() methode aufruft?
 
Das close-Event sollte aber ausgelöst werden. Poste doch mal deinen Code. Schonmal mit Firebug oder Wireshark geschaut ob die Verbindung geschlossen wird?
 
mal ein auszug:

Code:
http.createServer(function(req, res) {
    
    so('connection established');
    so('Remote IP: ' + req.connection.remoteAddress);
    so('x-forwarded-for: ' + req.headers['x-forwarded-for']);
    so('Agent: ' + req.headers['user-agent']);
    
    so('');
    
    //req.connection.setTimeout(30000);
    
    req.connection.on('close', function() {
        so('Verbdinung zu ' + test.id + ' geschlossen'); 
    });
    
    req.connection.on('error', function() {
        so('Verbdinung ' + test.id + ' fehler verursacht'); 
    });
    
    req.connection.on('end', function() {
        so('Verbdinung zu ' + test.id + ' beendet'); 
    });
    
        
    res.on('close', function() {
         so('Respond zu ' + test.id + ' geschlossen!'); 
    });
    res.on('error', function() {
         so('Respond ' + test.id + ' hat einen fehler verursacht!'); 
    });
    res.on('clientError', function() {
         so('Respond ' + test.id + ' client error!'); 
    });
    res.on('end', function() {
         so('Respond zu ' + test.id + ' beendet!'); 
    });
    
    req.on('close', function() {
         so('Request zu ' + test.id + ' geschlossen!'); 
    });
    req.on('error', function() {
         so('Request ' + test.id + ' hat einen fehler verursacht!'); 
    });
    req.on('end', function() {
         so('Request zu ' + test.id + ' beendet!'); 
    });
    
    var test = new Object();
    
    test.ip =  req.headers['x-forwarded-for'];
    test.agent =  req.headers['user-agent'];
    test.res = res;
    test.id = ++_global_id;

    clients.push(test);
    
    so(clients.length + ' Clienten verbunden');
    
    sendSSEHeader(res, test.id);
    
    // Alle 3 Sekunden eine nachricht schicken */
    setInterval(function() {
        checkConnection(res, test.id);
    }, 3000);
    
}).listen(8765);

so('Server running at 8765');

function sendSSEHeader(res, id) {
        
    so('Header gesendet zu: ' + id);
    
    res.writeHead(200, {
        'Content-Type': 'text/event-stream; charset=utf-8',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });

}

function checkConnection(res, id) {
    so('dump');
    res.write('id: ' + (new Date() + Math.random()) + '\n');
    res.write('data: dump\n\n');
}

das ist die ausgabe wenn ich die verbdinung beende:

Code:
15 Aug 17:52:45 - Verbdinung zu 1 beendet
15 Aug 17:52:45 - Request zu 1 geschlossen!
15 Aug 17:52:45 - Respond zu 1 geschlossen!
15 Aug 17:52:45 - Verbdinung zu 1 geschlossen

ich habe die verbindung manuell um 17:52:33 geschlossen, zwischendurch wurden noch 4 dump packete verschickt :/

'so' ist dabei nur eine funktion um die daten ein wenig "schöner" auf der konsole auszugeben.

und ja, wie ich bereits sagte, die eventsoure befindet sich um Status 2, was laut w3c sepzifikation bedeutet die verbindung ist geschlossen und es soll kein reconnect vorgenommen werden.

Meist beende ich sie direkt selber über die debug console von chrome.

chrome indess merkt übrigens sofort wenn ich den server abschalte und triggert das onerror event!

dem socket ein timeout zu geben bringt btw. auch nichts, was aber logisch ist da man vom clienten ja keine weiteren daten erwartet.

Aber ich hätte erwartet das man für jedes event das man sendet ein ack zurück bekommen müsste. Kann es sein das der timeout des ack zu hoch eingestellt ist?

P.S.
der dump prozess läuft hier ja auch weiter wenn alle verbinungen zu sind, wieso fliegen mir da nicht unmengen an fehlern um die ohren?
 
Zuletzt bearbeitet:
Dass das nicht funktioniert, kann ich mir vorstellen ;)

Mit req.connection greifst du auf den TCP/IP-Socket der HTTP-Verbindung zu, dank KeepAlive kann diese Verbindung aber weiterleben, wenn dein Client den SSE schließt.
Laut node.js Doku ist das request-Objekt direkt ein EventEmitter und löst das "close" Event aus. Also müsstest du in deinem Code nur den Zugriff auf die connection-Property entfernen und es funktioniert.
 
nah, den teil mit dem socket habe ich ganz am ende hinzugefügt, habe diese verdammte dokumentation von vorne bis hinten durchgearbeitet xD

daran liegts nicht, habs nun gerade testweise mal wieder entfernt, das resultat bleibt das selbe, nur mit 2 beendet meldungen weniger.

das es am keep-alive liegen könnte habe ich mir auch zusammen gereimt, deshalb ja meine frage wieso close kein "bye" signal an den server sendet bzw. wieso nicht geprüft wird ob de pakete ankommen, wo doch nun schon extra TCP benutzt wird.....
 
Zurück
Oben