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

ServerClientServerClientHTTP request and response lifecycleThe server cannot send a normal response whenever new data arrivesWebSocket lifecycle begins with HTTPStep 1: HTTP requestStep 2: HTTP responseStep 3: New HTTP request for an updateStep 4: HTTP response with the updateStep 5: HTTP GET with Upgrade: websocketStep 6: 101 Switching ProtocolsStep 7: WebSocket messageStep 8: WebSocket messageStep 9: Server pushes a new updateStep 10: Close frameStep 11: Close frame

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 GET request with headers such as Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Key, and Sec-WebSocket-Version.
  • 3. Accept the upgrade — The server replies with 101 Switching Protocols. The Sec-WebSocket-Accept header 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 CONNECT frame:

      CONNECT
      accept-version:1.2
      host:example.org
       
      ^@
    • A STOMP client can send a SEND frame to a named destination, such as /topic/orders.

      SEND
      destination:/topic/orders
      content-type:application/json
       
      {"orderId":"123"}^@
    • A client can use a SUBSCRIBE frame 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 (ACK and NACK), transactions (BEGIN, COMMIT, and ABORT), 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_EVENT and BINARY_ACK — Send an event or acknowledgement that includes binary data.
    • A connection to the main namespace starts with a CONNECT packet. If the server accepts it, the server replies with another CONNECT packet that contains a Socket.IO session ID.

      Client: { type: CONNECT, namespace: "/" }
      Server: { type: CONNECT, namespace: "/", data: { sid: "..." } }
    • An EVENT packet 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 ACK packet 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"}]: 4 identifies an Engine.IO message and 2 identifies 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?

AreaSocket.IOSTOMP
Main purposeEvent-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.
TypeA library ecosystem with its own protocolA protocol specification
Message modelNamed 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.
TransportUses Engine.IO, which can use WebSocket, WebTransport, or HTTP long-pollingUses a reliable two-way connection, such as WebSocket or TCP. STOMP does not use HTTP long-polling itself.
Connection recoveryProvides reconnection and packet buffering featuresDefines heartbeats, but reconnection behavior depends on the client and server
Routing modelThe 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.
InteroperabilityBoth sides need compatible Socket.IO implementationsIndependent clients and servers can interoperate when they follow the STOMP specification
Use caseLive 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?

AreaWebSocketsSocket.IOSTOMP
TransportA 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 providesA long-lived, two-way connection and framesEvents, namespaces, acknowledgements, reconnection, and fallback transportsDestinations, subscriptions, acknowledgements, transactions, receipts, and heartbeats
Message formatThe 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 casesA 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

← SSL, TLS & mTLS