The HTTP request-response model is the primary communication model of the web. In this model, a client (usually a browser) sends a request for a resource to a server, the server processes the requests, then sends back a response accordingly. For this communication to happen, both the server and the client must establish a connection (e.g., a TCP connection), and when the request-response cycle ends, the connection will be closed.
This model was sufficient for early web applications, because early websites were only displaying static content. But as the web evolved, the need arose to allow servers send data to clients without a client requesting it first. This led to push technology.
Push technology is a style of internet-based communication in which the request for a given transaction is initiated by the server. For example, in timeline updates in social media apps, the server pushes data to the client without the client requesting it.
As the HTTP request-response model was not designed for these use cases, different mechanisms were invented. These mechanisms are server-sent events (SSE) and WebSockets.
In this article, we will learn about server-sent events and WebSockets, including how they work and their individual use cases, so you can make an informed decision about which to use in your next project.
As the name suggest, server-sent events are a push technology that allows the client to receive data automatically from the server through an HTTP connection. In this case, after an HTTP connection has been established between the server and the client, the server can send automatic updates.
EventSource. The source of the event will be passed to
EventSource during instantiation, which will handle connection to the source so clients will get updates sent automatically.
You can think of SSEs as a long-running HTTP request that sends data out to the client whenever the server wants.
Direction of data flow in server-sent events
As illustrated in the diagram above, SSEs are unidirectional, so they allow sending data from the server to the client only. SSEs are designed to be more efficient than long polling, and include some great features:
- Automatic reconnection: if a client loses connection to the event source, reconnection is automatically retried after a certain amount of time (the length of which can be customized)
- Event IDs: every event sent can be assigned a unique identifier
- The ability to send arbitrary events
Data transmission format
SSEs transmit data in text-encoded UTF-8.
WebSocket is a communication protocol that provides bidirectional communication channels over a single TCP connection. Unlike SSEs, which are transmitted over simple HTTP, WebSocket has its own protocol called – you guessed it – the WebSocket Protocol.
A WebSocket connection starts as a normal HTTP connection which through the WebSocket handshake is upgraded to a WebSocket connection. The handshake starts as an HTTP request from the client with a special
UPGRADE header, then the server receives the request, processes it, and switches to the WebSocket protocol if the request is accepted.
When this handshake is complete, then bidirectional communication is possible; the client can send data to the server and the server can also send data back to the client.
The following are sample WebSocket Protocol handshake requests.
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
As mentioned earlier, the server will switch protocols if the handshake is successful. The status code for a successful switch in protocols is
Data transmission format in WebSocket
WebSocket can transmit data in both UTF-8 encoded text and in binary format. Transmitting data in binary can increase the speed of transmission and interpretation of data, as all the values of a byte can be used in encoding.
If data is encoded in text (UTF-8 in this case), only the binary values corresponding to characters in UTF-8 encoding are utilized. Binary encoding has the benefit of efficiency.
More great articles from LogRocket:
- Don't miss a moment with The Replay, a curated newsletter from LogRocket
- Use React's useEffect to optimize your application's performance
- Switch between multiple versions of Node
- Learn how to animate your React app with AnimXYZ
- Explore Tauri, a new framework for building binaries
- Compare NestJS vs. Express.js
- Discover popular ORMs used in the TypeScript landscape
Use cases for SSE and WebSocket
You might have noticed that WebSocket can do what SSE can do and more, so why not just use WebSockets only?
SSE is best used when it’s not necessary to send data from client to server. For example, in status updates and push notification applications, the data flow is from the server to the client only. This is what SSE is designed for, so WebSocket would be overkill. It’s always wise to use the best tool for the job.
WebSocket is best used when we need real time, two-way communication, like in chatting apps or multiplayer games. WebSocket was designed to handle those kind of use cases.
In this article, we have discussed the HTTP request-response model and how it is not sufficient for pushing data from the server to client.
We also learned that server-sent events are long running HTTP requests through which the server can send data to the client whenever it wants. WebSocket, on the other hand, is a completely new protocol that uses HTTP for connection, then proceeds to the WebSocket handshake before two way communication can be established.
LogRocket: Full visibility into your web and mobile apps
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.