javascript - sent - eventsource vs websocket
JavaScript EventSource SSE no se dispara en el navegador (3)
He modificado la secuencia de comandos del lado del servidor, que ''parece'' funciona en parte para Chrome.
Pero el corte de conexión por cada 2 transmisiones y solo 1 puede mostrarse en el cliente.
Firefox funciona para la primera emisión y pasa por este error:
Error: la conexión a / sse se interrumpió mientras se cargaba la página.
Y Chrome intentará volver a conectarse y recibió la tercera emisión.
Creo que también está relacionado con la configuración del firewall, pero no puedo explicar por qué alguna vez funcionará.
Nota : Para el detector de eventos de respuesta (línea 10), ''cerrar'' y ''terminar'' tienen un resultado diferente,
Puedes probarlo y mi resultado es [cerrar: 1 éxito / 2 transmisión] y [final: 1 éxito / 8 transmisión]
var http = require(''http''), fs = require(''fs''), requests = [];
var server = http.Server(function(req, res) {
var clientIP = req.socket.remoteAddress;
var clientPort = req.socket.remotePort;
if (req.url == ''/sse'') {
var allClient="";for(var i=0;i<requests.length;i++){allClient+=requests[i].ip+":"+requests[i].port+";";}
if(allClient.indexOf(clientIP+":"+clientPort)<0){
requests.push({ip:clientIP, port:clientPort, res:res});
res.on(''close'', function() {
console.log("client " + clientIP + ":" + clientPort + " died");
for(var i=requests.length -1; i>=0; i--) {
if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
requests.splice(i, 1);
}
}
});
}
}else{
res.writeHead(200, {''Content-Type'': ''text/html''});
res.write(fs.readFileSync(''./test.html''));
res.end();
}
});
server.listen(80);
setInterval(function test() {
broadcast(''poll'', "test message");
}, 500);
var broadcastCount=0;
function broadcast(rtype, msg) {
if(!requests.length)return;
broadcastCount++;
var lines = msg.split("/n");
for(var i = requests.length - 1; i >= 0; i--) {
requests[i].res.writeHead(200, {
''Content-Type'': ''text/event-stream'',
''Cache-Control'': ''no-cache'',
''Connection'': ''keep-alive''
});
requests[i].res.write("event: " + rtype + "/n");
for(var j = 0; j < lines.length; j++) {
if(lines[j]) {
requests[i].res.write("data: " + lines[j] + "/n");
}
}
requests[i].res.write("data: Count/: " + broadcastCount + "/n");
requests[i].res.write("/n");
}
console.log("Broadcasted " + broadcastCount + " times to " + requests.length + " user(s).");
}
He estado desarrollando un servidor nodejs para proporcionar eventos del lado del servidor para un nuevo sitio web que estoy desarrollando en HTML5.
Cuando telnet al servidor funciona correctamente, enviándome los encabezados de respuesta HTTP requeridos seguidos de un flujo de eventos que estoy generando actualmente cada 2 o 3 segundos solo para demostrar que funciona.
He probado la última versión de FireFox, Chrome y Opera y ellos crean el objeto EventSource y se conectan al servidor de nodejs. De acuerdo, ninguno de los navegadores genera ninguno de los eventos, incluidos onopen, onmessage y onerror.
Sin embargo, si detengo mi servidor nodejs, finalizando la conexión desde los navegadores, todos ellos envían de repente todos los mensajes y se muestran todos mis eventos. Todos los navegadores intentan volver a conectarse al servidor según las especificaciones.
Estoy alojando todo en un servidor web. nada se está ejecutando en los archivos locales.
He leído todo lo que puedo encontrar en línea, incluidos los libros que he comprado y nada indica ningún problema de este tipo. ¿Se me escapa algo?
Una implementación de servidor de muestra
var http = require(''http'');
var requests = [];
var server = http.Server(function(req, res) {
var clientIP = req.socket.remoteAddress;
var clientPort = req.socket.remotePort;
res.on(''close'', function() {
console.log("client " + clientIP + ":" + clientPort + " died");
for(var i=requests.length -1; i>=0; i--) {
if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
requests.splice(i, 1);
}
}
});
res.writeHead(200, {
''Content-Type'': ''text/event-stream'',
''Access-Control-Allow-Origin'': ''*'',
''Cache-Control'': ''no-cache'',
''Connection'': ''keep-alive''});
requests.push({ip:clientIP, port:clientPort, res:res});
res.write(": connected./n/n");
});
server.listen(8080);
setInterval(function test() {
broadcast(''poll'', "test message");
}, 2000);
function broadcast(rtype, msg) {
var lines = msg.split("/n");
for(var i=requests.length -1; i>=0; i--) {
requests[i].res.write("event: " + rtype + "/n");
for(var j=0; j<lines.length; j++) {
if (lines[j]) {
requests[i].res.write("data: " + lines[j] + "/n");
}
}
requests[i].res.write("/n");
}
}
Una muestra de página html
<!DOCTYPE html>
<html>
<head>
<title>SSE Test</title>
<meta charset="utf-8" />
<script language="JavaScript">
function init() {
if(typeof(EventSource)!=="undefined") {
var log = document.getElementById(''log'');
if (log) {
log.innerHTML = "EventSource() testing begins..<br>";
}
var svrEvents = new EventSource(''/sse'');
svrEvents.onopen = function() {
connectionOpen(true);
}
svrEvents.onerror = function() {
connectionOpen(false);
}
svrEvents.addEventListener(''poll'', displayPoll, false); // display multi choice and send back answer
svrEvents.onmessage = function(event) {
var log = document.getElementById(''log'');
if (log) {
log.innerHTML += ''message: '' + event.data + "<br>";
}
// absorb any other messages
}
} else {
var log = document.getElementById(''log'');
if (log) {
log.innerHTML = "EventSource() not supported<br>";
}
}
}
function connectionOpen(status) {
var log = document.getElementById(''log'');
if (log) {
log.innerHTML += ''connected: '' + status + "<br>";
}
}
function displayPoll(event) {
var html = event.data;
var log = document.getElementById(''log'');
if (log) {
log.innerHTML += ''poll: '' + html + "<br>";
}
}
</script>
</head>
<body onLoad="init()">
<div id="log">testing...</div>
</body>
</html>
Estos ejemplos son básicos pero de la misma variedad que cualquier otra demostración que he visto en libros y en línea. El eventSource solo parece estar funcionando si finalizo una conexión de cliente o finalizo el servidor, pero esto sería un sondeo en lugar de un SSE y en particular quiero usar el SSE.
Curiosamente, las demostraciones, como Thouse de html5rock tampoco parecen funcionar como se esperaba cuando las uso en línea.
lo rompió! :)
Gracias a la ayuda de Tom Kersten que me ayudó con las pruebas. Resulta que el código no es el problema.
Tenga cuidado ... si su cliente utiliza algún tipo de software antivirus que intercepte solicitudes web, puede causar problemas aquí. En este caso, Sophos Endpoint Security, que proporciona protección antivirus y firewall de nivel empresarial, tiene una función llamada protección web. Dentro de estas características hay una opción para escanear descargas; Parece que la conexión SSE se trata como una descarga y, por lo tanto, no se libera en el navegador hasta que la conexión se cierra y la transmisión se recibe para escanear. Deshabilitar esta opción cura el problema. He enviado un informe de error pero otros sistemas antivirus pueden hacer lo mismo.
Gracias por tus sugerencias y ayuda a todos :)
http://www.w3.org/TR/eventsource/#parsing-an-event-stream
Dado que se espera que las conexiones establecidas a los servidores remotos para tales recursos sean de larga duración, los UA deben garantizar que se utiliza el almacenamiento en búfer adecuado. En particular, si bien el búfer de línea con líneas está definido para terminar con un solo carácter U + 000A LINE FEED (LF) es seguro, el búfer de bloque o el búfer de línea con diferentes finales de línea esperados pueden causar retrasos en el envío de eventos.
Intente jugar con los finales de línea ( "/r/n"
lugar de "/n"
).
http://www.w3.org/TR/eventsource/#notes
También se advierte a los autores que la fragmentación HTTP puede tener efectos negativos inesperados en la confiabilidad de este protocolo. Donde sea posible, la fragmentación debe deshabilitarse para servir secuencias de eventos a menos que la tasa de mensajes sea lo suficientemente alta para que esto no importe.