Jak faktycznie działają zdarzenia wysłane przez serwer?

Więc rozumiem pojęcie zdarzeń wysyłanych przez serwer(EventSource):

  • klient łączy się z punktem końcowym poprzez EventSource
  • Klient tylko nasłuchuje wiadomości wysyłanych z punktu końcowego
Nie wiem, jak to działa na serwerze. Przyjrzałem się różnym przykładom, ale ten, który przychodzi mi na myśl to Mozilla: http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/

Teraz to może być po prostu zły przykład, ale to trochę ma sens jak działa strona serwera, jak to Rozumiem:

  • coś zmienia się w magazynie danych, np. w bazie danych
  • skrypt po stronie serwera sprawdza magazyn danych co N-tą sekundę
  • jeśli skrypt ankiety zauważy zmianę, Zdarzenie wysłane przez serwer zostanie wywołane do klientów
Czy to ma sens? Czy naprawdę tak to działa z perspektywy barebones?
Author: Ahmed Nuaman, 2011-10-03

1 answers

Witryna HTML5 doctor ma świetny zapis na wysyłanych przez serwer zdarzeniach, ale postaram się podać (rozsądnie) krótkie podsumowanie również tutaj.

Zdarzenia wysłane przez serwer są w istocie połączeniem http, specjalnym typem mime (text/event-stream) i agentem użytkownika, który dostarcza API EventSource. Razem tworzą one fundament jednokierunkowego połączenia między serwerem a klientem, gdzie wiadomości mogą być wysyłane z serwera do klienta.

Na serwerze side, to raczej proste. Wszystko, co naprawdę musisz zrobić, to ustawić następujące nagłówki http:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

Pamiętaj, aby odpowiedzieć kodem 200, a nie 204 lub innym kodem, ponieważ spowoduje to odłączenie zgodnych agentów Użytkownika. Upewnij się również, że nie zakończysz połączenia po stronie serwera. Teraz możesz zacząć przesuwać wiadomości w dół tego połączenia. W nodejs (używając express) może to wyglądać mniej więcej tak:

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")
})

Na kliencie, wystarczy użyć EventSource API, jak zauważyłeś:

var source = new EventSource("/my-stream")
source.addEventListener("message", function(message) {
    console.log(message.data)
})

I to wszystko, w zasadzie.

Teraz, w praktyce, to, co się tutaj dzieje, to to, że połączenie jest utrzymywane przy życiu przez serwer i klienta za pomocą obopólnej umowy. Serwer utrzyma połączenie przy życiu tak długo, jak uzna to za stosowne. Jeśli chce, może zakończyć połączenie i odpowiedzieć 204 No Content następnym razem, gdy klient spróbuje się połączyć. Spowoduje to, że klient przestanie próbować ponownie połączyć się. Nie jestem pewien, czy jest sposób na zakończenie połączenie w taki sposób, że klient jest informowany, aby w ogóle nie nawiązywać połączenia, tym samym pomijając klienta próbującego nawiązać połączenie raz.

Jak wspomniano, klient również utrzyma połączenie przy życiu i spróbuje ponownie połączyć się, jeśli zostanie przerwane. Algorytm do ponownego połączenia jest określony w specyfikacji i jest dość prosty.

Jeden bardzo ważny bit, który do tej pory ledwo dotknął się jednak jest typ mime. Typ mime definiuje format wiadomości schodzącej w dół łączę się. Zauważ jednak, że to nie dyktuje formatu treści wiadomości, tylko strukturę samych wiadomości. Typ mime jest bardzo prosty. Wiadomości są zasadniczo parami klucz / wartość informacji. Klucz musi być jednym z predefiniowanych zestawów:

  • id-identyfikator wiadomości
  • dane-dane rzeczywiste
  • event-typ zdarzenia
  • retry-milleseconds agent użytkownika powinien poczekać przed ponowną próbą nieudanego połączenie

Wszelkie inne klucze powinny być ignorowane. Wiadomości są następnie rozdzielane za pomocą dwóch znaków nowego wiersza: \n\n

Poniżej znajduje się prawidłowa wiadomość: (ostatnie nowe znaki linii dodane dla verbosity)

data: Hello, world!
\n

Klient zobaczy to jako: Hello, world!.

Jak to jest:

data: Hello,
data: world!
\n

Klient zobaczy to jako: Hello,\nworld!.

To w sumie podsumowuje, czym są zdarzenia wysyłane przez serwer: długo działające, nie buforowane połączenie http, typ mime i simple javascript API.

Aby uzyskać więcej informacji, Zdecydowanie sugeruję przeczytanie specyfikacji . Jest mały i opisuje rzeczy bardzo dobrze (chociaż wymagania Po stronie serwera mogłyby być nieco lepiej podsumowane.) Sugeruję przeczytanie go dla oczekiwanego zachowania z pewnymi kodami statusu http, na przykład.

 47
Author: Marcus Stade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 18:07:12