server sent events - support - ¿Cómo funcionan realmente los eventos enviados por el servidor?
server sent events php (1)
El sitio médico de HTML5 tiene una gran reseña de los eventos enviados por el servidor, pero también intentaré proporcionar un resumen (razonablemente) aquí.
Los eventos enviados por el servidor son, en esencia, una conexión http de larga duración, un tipo mime especial ( text/event-stream
) y un agente de usuario que proporciona la API EventSource
. Juntos, estos constituyen la base de una conexión unidireccional entre un servidor y un cliente, donde los mensajes se pueden enviar de un servidor a otro .
En el lado del servidor, es bastante simple. Todo lo que necesitas hacer es configurar los siguientes encabezados http:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Asegúrese de responder con el código 200
y no 204
o cualquier otro código, ya que esto hará que los agentes de usuario compatibles se desconecten. Además, asegúrese de no terminar la conexión en el lado del servidor. Ahora puede comenzar a enviar mensajes a través de esa conexión. En nodejs (using express), esto podría parecerse a lo siguiente:
app.get("/my-stream", function(req, res) {
res.status(200)
.set({ "content-type" : "text/event-stream"
, "cache-control" : "no-cache"
, "connection" : "keep-alive"
})
res.write("data: Hello, world!/n/n")
})
En el cliente, solo usa la API de EventSource
, como anotó:
var source = new EventSource("/my-stream")
source.addEventListener("message", function(message) {
console.log(message.data)
})
Y eso es todo, básicamente.
Ahora, en la práctica, lo que realmente sucede aquí es que la conexión se mantiene viva por el servidor y el cliente mediante un contrato mutuo. El servidor mantendrá la conexión activa durante el tiempo que considere oportuno. Si lo desea, puede finalizar la conexión y responder con un 204 No Content
próxima vez que el cliente intente conectarse. Esto hará que el cliente deje de intentar volver a conectarse. No estoy seguro de si hay una manera de finalizar la conexión de manera que se le diga al cliente que no se vuelva a conectar, por lo que se salta al cliente que intenta volver a conectarse una vez.
Como se mencionó, el cliente también mantendrá la conexión activa e intentará reconectarse si se cae. El algoritmo para reconectarse se especifica en la spec , y es bastante directo.
Un bit súper importante que hasta ahora apenas he tocado es el tipo mime. El tipo mime define el formato del mensaje que viene por la conexión. Sin embargo, tenga en cuenta que no dicta el formato del contenido de los mensajes, solo la estructura de los mensajes en sí. El tipo mime es extremadamente sencillo. Los mensajes son esencialmente pares de información clave / valor. La clave debe ser una de un conjunto predefinido:
- id - el id del mensaje
- datos - los datos reales
- evento - el tipo de evento
- Reintentar - milisegundos el agente de usuario debería esperar antes de reintentar una conexión fallida
Cualquier otra clave debe ser ignorada. Los mensajes se delimitan mediante el uso de dos caracteres de nueva línea: /n/n
El siguiente es un mensaje válido: (últimos caracteres de línea nuevos agregados para verbosidad)
data: Hello, world!
/n
El cliente verá esto como: Hello, world!
.
Como es esto:
data: Hello,
data: world!
/n
El cliente verá esto como: Hello,/nworld!
.
Eso resume bastante bien lo que son los eventos enviados por el servidor: una conexión http no almacenada en caché de larga duración, un tipo mime y una simple API de javascript.
Para más información, sugiero encarecidamente leer la specification . Es pequeño y describe las cosas muy bien (aunque los requisitos del servidor pueden resumirse un poco mejor). Recomiendo leerlo para ver el comportamiento esperado con ciertos códigos de estado de http, por ejemplo.
Así que entiendo el concepto de eventos enviados por el servidor ( EventSource
):
- Un cliente se conecta a un punto final a través de
EventSource
- El cliente solo escucha los mensajes enviados desde el punto final
Estoy confundido acerca de cómo funciona en el servidor. He echado un vistazo a diferentes ejemplos, pero el que me viene a la mente es el de Mozilla: http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/
Ahora bien, esto puede ser solo un mal ejemplo, pero tiene sentido cómo funcionaría el lado del servidor, tal como lo entiendo:
- Algo cambia en un almacén de datos, como una base de datos
- Un script del lado del servidor sondea el almacén de datos cada N segundo
- Si la secuencia de comandos de sondeo nota un cambio, se activa un evento enviado por el servidor a los clientes
¿Tiene sentido? ¿Es así realmente como funciona desde una perspectiva de barebones?