Dev Learning Lab

The labs on this site need JavaScript to run. The same content is written out below.

Learn › Networking › HTTP

Polling, SSE, and WebSocket

Four ways to tell the browser what happened on the server

HTTP works by the client asking and the server answering, so even when the server has a new notification, it cannot speak first. The options are to ask periodically (polling), to hold the answer back (long polling), to keep the connection open and stream data through it (SSE), or to switch to a two-way channel (WebSocket).

Checked against documentation and standards · Checked against the HTML standard, the WebSocket standard (RFC 6455), and the Spring documentation

Concepts in this lab

SSE (server-sent events) and polling
Polling is an approach in which the client repeatedly asks the server, at regular intervals, whether there is new data. SSE keeps one HTTP connection open while the server keeps sending events to the client, and data can travel in one direction only, from the server to the client. For cases such as notifications, where only the server needs to send, it is simpler than WebSocket.
WebSocket
A communication protocol that lets a client and a server keep one connection open and send messages freely from either side. In HTTP, the server can respond only after the client sends a request. With this protocol, the server can send data first, so it is used for chat and real-time notifications.
HTTP as a stateless protocol
HTTP is a communication protocol in which a client sends a request and a server responds. Stateless means that the server does not remember the content of earlier requests, so each request must carry all the information needed to process it. Because the server keeps no state, any server can take a request, which makes it easy to add servers. Information that must carry over, such as a login state, is kept with cookies, sessions, or tokens.

Try these

Running with the default settings

  1. Every 5 seconds, the browser requests "Are there any new notifications?" The server returns the notifications that have piled up until then, or an empty response if there are none.
  2. 5s: The browser sent a request. It received the 1 notification created in the meantime. They were created at 3.7s, but had to wait until the next request.
  3. 10s: The browser sent a request. There were no new notifications, so it received an empty response.
  4. 15s: The browser sent a request. It received the 1 notification created in the meantime. They were created at 13.7s, but had to wait until the next request.
  5. 20s: The browser sent a request. There were no new notifications, so it received an empty response.
  6. 25s: The browser sent a request. It received the 1 notification created in the meantime. They were created at 23.7s, but had to wait until the next request.
  7. 30s: The browser sent a request. There were no new notifications, so it received an empty response.
  8. Of the 6 requests in 30 seconds, 3 ended empty-handed.

Result of this run

Code

// Browser
setInterval(async () => {
    const res = await fetch("/notifications?after=" + lastId);
    show(await res.json());              // an empty array if there is nothing
}, 5000);

Assumptions of this model

Notifications are assumed to be created evenly across the 30-second window. Network round-trip time is ignored in the delivery delay. The messages the client sends are fixed at 10 per 30 seconds. The long-polling time limit is set to 30 seconds. The behavior of the four methods follows the explanations in the HTML standard (EventSource), the WebSocket standard (RFC 6455), and the Spring documentation.

Previous lab: CORS · Next lab: TLS handshake

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these