WebSockets
How WebSockets create a long-lived, two-way connection between a client and a server
What are Websockets
- A WebSocket is a network protocol for two-way communication between a client and a server.
- Both sides can send data at any time.
- The client does not need to send a new request for every update.
- An HTTP connection usually follows a request and response pattern:
- The client sends a request.
- The server sends a response.
- This pattern works well for most web pages and APIs.
- It is less suitable for chat messages, live notifications, and multiplayer games. These applications need the server to send new data as soon as it is available.
- WebSockets solve this problem with one long-lived connection:
- The connection starts with an HTTP request.
- If the server accepts the upgrade, both sides switch to the WebSocket protocol.
- The connection stays open until the client, the server, or the network closes it.
- WebSockets do not define the meaning of application data. The application must define its own message format.
- For example, an application can send JSON messages such as
{"type":"chat.message","text":"Hello"}.
HTTP and WebSocket Lifecycles
WebSocket Connection Lifecycle
- 1. Open a network connection — The client opens a TCP connection to the server. A
wss://connection creates a TLS connection before the WebSocket handshake. - 2. Send the opening handshake — The client sends an HTTP
GETrequest with headers such asUpgrade: websocket,Connection: Upgrade,Sec-WebSocket-Key, andSec-WebSocket-Version. - 3. Accept the upgrade — The server replies with
101 Switching Protocols. TheSec-WebSocket-Acceptheader proves that the server received the client's handshake key. - 4. Exchange frames — The client and server send WebSocket frames in both directions on the same connection. A frame can carry text, binary data, a ping, a pong, or a close signal.
- 5. Close the connection — One side sends a close frame. The other side replies with a close frame. The network connection then closes.
WebSocket Frames and Messages
- A WebSocket connection sends frames, not HTTP requests and responses.
- A frame contains a small header and an optional payload.
- The header identifies the frame type and the payload length.
- The main frame types are:
- Text frame — Contains UTF-8 text. Many applications use a JSON string in a text frame.
- Binary frame — Contains bytes. It is useful for images, audio, protocol buffers, or other binary formats.
- Continuation frame — Continues a message that was split into multiple frames.
- Ping frame — Checks whether the other side is still reachable.
- Pong frame — Replies to a ping frame.
- Close frame — Starts the closing handshake. It can include a status code and a short reason.
- A message can use one frame or several frames. Splitting a large message into several frames is called fragmentation.
- Browsers must mask frames that they send to servers (XORs the payload with a random key). The random mask stops browser JavaScript from making WebSocket data look like an HTTP request or response to an old proxy or cache.
- Servers do not mask frames that they send to browsers.
- For example, a chat application can send this text message in one frame:
{"type":"chat.message","text":"Hello"}.
Protocols and Libraries
- WebSockets define how a client and server exchange frames. They do not define concepts such as topics, subscriptions, acknowledgements, or automatic reconnection.
- An application can define these features itself. It can also use a protocol or library that already provides them.
- STOMP is a text-based messaging protocol. It can run over a WebSocket connection or another reliable two-way connection, such as TCP.
-
WebSockets only send frames between a client and a server. STOMP adds a shared messaging model on top of those frames.
-
STOMP defines the wire format for its commands. A frame has a command, zero or more headers, an optional body, and a final NULL byte. The examples below show the NULL byte as
^@. -
A client opens a STOMP session with a
CONNECTframe:CONNECT accept-version:1.2 host:example.org ^@ -
A STOMP client can send a
SENDframe to a named destination, such as/topic/orders.SEND destination:/topic/orders content-type:application/json {"orderId":"123"}^@ -
A client can use a
SUBSCRIBEframe to receive messages from a destination. The server tracks subscriptions and routes matching messages to subscribers.SUBSCRIBE id:orders destination:/topic/orders ack:client ^@ -
STOMP defines commands for acknowledgements (
ACKandNACK), transactions (BEGIN,COMMIT, andABORT), receipts, and heartbeats. -
STOMP defines the command names and headers. It does not define the fields inside an application payload such as
{"orderId":"123"}. -
STOMP does not require a separate broker. Your WebSocket server can implement these destinations, subscriptions, and routing rules itself.
-
STOMP does not define whether a destination is durable, how messages are stored, or how delivery works. The server decides those details. -Use STOMP when several clients need standard broker-style messaging and a common messaging format.
-
- Socket.IO is a client-and-server library. It is not a plain WebSocket implementation.
-
It uses WebSocket when possible, but it can fall back to HTTP long-polling when WebSocket is unavailable.
-
It adds its own packet format. A plain WebSocket client cannot connect directly to a Socket.IO server.
-
It provides event names, automatic reconnection, acknowledgements, buffering, broadcasting, rooms, and namespaces.
-
Socket.IO runs on top of Engine.IO. Engine.IO manages the low-level transport, including WebSocket upgrades, long-polling fallback, and heartbeats. Socket.IO adds namespaces, events, and acknowledgements.
-
A Socket.IO packet contains a packet type, a namespace, an optional payload, and an optional acknowledgement ID.
-
The common packet types are:
CONNECT— Opens a connection to a namespace, such as/or/admin.CONNECT_ERROR— Tells the client that a namespace connection was refused.EVENT— Sends an event name and its data to the other side.ACK— Replies to an event that requested an acknowledgement.DISCONNECT— Ends a connection to a namespace.BINARY_EVENTandBINARY_ACK— Send an event or acknowledgement that includes binary data.
-
A connection to the main namespace starts with a
CONNECTpacket. If the server accepts it, the server replies with anotherCONNECTpacket that contains a Socket.IO session ID.Client: { type: CONNECT, namespace: "/" } Server: { type: CONNECT, namespace: "/", data: { sid: "..." } } -
An
EVENTpacket holds a non-empty array. The first item is usually the event name and later items are event data.Client: { type: EVENT, namespace: "/", data: ["chat.message", {"text":"Hello"}] } -
The sender can add an acknowledgement ID to an event. The receiver replies with an
ACKpacket that has the same ID.Client: { type: EVENT, namespace: "/", data: ["save", {"id":"123"}], id: 12 } Server: { type: ACK, namespace: "/", data: ["saved"], id: 12 } -
Socket.IO encodes these packets before it sends them. For example, the built-in encoder sends a main-namespace event as a value similar to
42["chat.message",{"text":"Hello"}]:4identifies an Engine.IO message and2identifies a Socket.IO event. -
Use Socket.IO when you want these application features and control both the client and server libraries.
-
FAQs
What is the difference between Socket.IO and STOMP?
| Area | Socket.IO | STOMP |
|---|---|---|
| Main purpose | Event-based communication between an application client and server. Socket.IO works over Engine.IO, which can use WebSocket, WebTransport, or HTTP long-polling. | Standard messaging between clients and a server that routes messages. STOMP can run over WebSocket or a direct reliable TCP connection. |
| Type | A library ecosystem with its own protocol | A protocol specification |
| Message model | Named application events with argument data. Common examples include chat.message, user.typing, order.updated, and notification. These names are defined by the application. | Standard commands and destinations. A client uses commands such as CONNECT, SEND, SUBSCRIBE, ACK, and DISCONNECT. |
| Transport | Uses Engine.IO, which can use WebSocket, WebTransport, or HTTP long-polling | Uses a reliable two-way connection, such as WebSocket or TCP. STOMP does not use HTTP long-polling itself. |
| Connection recovery | Provides reconnection and packet buffering features | Defines heartbeats, but reconnection behavior depends on the client and server |
| Routing model | The packet namespace, such as /admin, separates traffic. The server uses rooms and broadcasts to choose recipients. The server can emit an event such as chat.message to a room, but the event name itself does not route the packet. | A SEND or SUBSCRIBE command includes a destination header, such as /topic/orders. The server uses that destination to route a MESSAGE frame to subscribers. |
| Interoperability | Both sides need compatible Socket.IO implementations | Independent clients and servers can interoperate when they follow the STOMP specification |
| Use case | Live collaboration, chat, dashboards, and multiplayer games where one application controls the web or mobile client and server. For example, a chat server can emit chat.message to a room for one conversation. | Notifications, order updates, and enterprise systems that need a common client-to-broker protocol. For example, services can SEND order events to /topic/orders, while dashboards SUBSCRIBE to that destination. |
How do WebSockets, Socket.IO, and STOMP differ?
| Area | WebSockets | Socket.IO | STOMP |
|---|---|---|---|
| Transport | A transport protocol over TCP. A secure wss:// connection adds TLS. | A library and application protocol over Engine.IO. Engine.IO can use WebSocket, WebTransport, or HTTP long-polling. | A general application messaging protocol over a reliable two-way connection, such as WebSocket or TCP. |
| What it provides | A long-lived, two-way connection and frames | Events, namespaces, acknowledgements, reconnection, and fallback transports | Destinations, subscriptions, acknowledgements, transactions, receipts, and heartbeats |
| Message format | The application defines the payload. WebSocket frame types include text, binary, continuation, ping, pong, and close. | Socket.IO packets include CONNECT, CONNECT_ERROR, EVENT, ACK, DISCONNECT, BINARY_EVENT, and BINARY_ACK. | STOMP frames contain a command, headers, an optional body, and a NULL byte. Common commands include CONNECT, SEND, SUBSCRIBE, ACK, NACK, MESSAGE, RECEIPT, and DISCONNECT. |
| Use cases | A custom live-price feed, a browser game, or direct communication with a service where you define the message format. | A chat application with rooms and automatic reconnection, a collaborative editor, or a multiplayer game where you control the client and server. | An order-event topic shared by services and dashboards, enterprise notifications, or a browser client connected to a STOMP messaging server. |
References
- RFC 6455 — The WebSocket Protocol
- RFC 8441 — Bootstrapping WebSockets with HTTP/2
- RFC 7692 — Compression Extensions for WebSocket
- WebTransport over HTTP/3 — active IETF Internet-Draft
- RFC 9221 — An Unreliable Datagram Extension to QUIC
- STOMP Protocol Specification, Version 1.2
- Socket.IO Protocol, Version 5