IoT(Internet Of Things)

 

 

 

Application Protocol - WebSocket

 

A web page normally talks to its server with HTTP requests, and each request gets exactly one response. That model does not fit an IoT dashboard or a chat window, where the server must push data at any time. WebSocket solves this with one long-lived, two-way connection. This page explains what WebSocket is and walks through a real opening handshake from an MQTT client in a browser. Then it shows how data is framed on the open connection.

What is WebSocket ?

WebSocket sounds like "A special socket that is specially designed/optimized for Web Application". It sounds OK.. but what it really mean ? The official definition of WebSocket is defined in RFC 6455 as stated below.

The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for this is the origin-based security model commonly used  by web browsers.  The protocol consists of an opening handshake  followed by basic message framing, layered over TCP.  The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or <iframe>s and long polling).

Whenever I try to clearly understand anything from RFC, I almost always have to rewrite things on my own format / words, otherwise it tend to be very confusing. Let me rewrite this statement from RFC document. It goes as follows.

  • WebSocket is a kind of two-way communication between a client and a remote host
  • The client is running untrusted code in a controlled environment and the remote host has opted-in to communication from that code.
  • WebSocket uses the origin-based security model
  • WebSocket protocol is layered over TCP
  • Overal protocol sequence of WebSocket is
    • Opening Handshake
    • Basic Message Framing
  • The WebSocket Protocol is an independent TCP-based protocol.  Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request (RFC 6455 1.7.  Relationship to TCP and HTTP)

Opening Handshake

Every WebSocket connection starts as an ordinary HTTP request on a TCP connection. The client asks the server to upgrade that connection, and the server agrees with status code 101. The table below lists the two messages, and the captures after it show every header they carry.

 

 

Direction

Message

(1)

Client --> Server

GET /protocol HTTP/1.1 (Host url etc)

(2)

Client <-- Server

HTTP/1.1 101 Switching Protocols

 

(1) GET /protocol HTTP/1.1 (Host url etc)

 

Captured HTTP request, client to server. Header values are from a live capture of an MQTT client in a browser, not from the specification.

GET /mqtt HTTP/1.1
Host: broker.mqttdashboard.com:8000
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://www.hivemq.com
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Sec-WebSocket-Key: OfMWmQZlMFBWe/o7k1CzZg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: mqttv3.1

The request is a normal HTTP GET, but the highlighted headers turn it into a WebSocket request. Connection: Upgrade and Upgrade: websocket ask the server to switch protocols on this TCP connection. Sec-WebSocket-Version: 13 is the version defined in RFC 6455. Sec-WebSocket-Key is 16 random bytes in base64, and the client picks a new one for every connection.

Two more headers matter for this capture. Sec-WebSocket-Protocol names the application protocol the client wants to run inside WebSocket, here mqttv3.1. Origin tells the server which web page opened the connection, and this is how the origin-based security model from the RFC works in practice. The server can refuse a connection from an origin it does not trust. The client also offers compression with Sec-WebSocket-Extensions: permessage-deflate.

 

(2) HTTP/1.1 101 Switching Protocols

 

Captured HTTP response, server to client. Header values are from a live capture, not from the specification.

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: PqfV+Vb3mDtpMlZ/bO+GBzyX4N8=
Sec-WebSocket-Protocol: mqttv3.1

Let's check the one header that proves the server understood the request. The server takes the Sec-WebSocket-Key, appends the fixed GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, computes SHA-1 over the result, and encodes it in base64. For the key OfMWmQZlMFBWe/o7k1CzZg== this gives PqfV+Vb3mDtpMlZ/bO+GBzyX4N8=, which is exactly the Sec-WebSocket-Accept value in the capture. The client repeats this calculation, and it closes the connection if the values differ.

Also compare what the response leaves out. The server repeats Sec-WebSocket-Protocol: mqttv3.1, so the two sides agree to run MQTT. But the response carries no Sec-WebSocket-Extensions header, so compression was not agreed. From this point, the same TCP connection carries WebSocket frames instead of HTTP.

  • The handshake is an HTTP Upgrade : it lets WebSocket pass through ports, proxies and servers that already handle HTTP.
  • Sec-WebSocket-Accept proves the server read the request : it is the base64 SHA-1 of the client key plus a fixed GUID.
  • The server confirms only what it supports : here it accepted the mqttv3.1 subprotocol and declined permessage-deflate.

How is data framed after the handshake ?

After the 101 response, HTTP is gone and both sides exchange WebSocket frames. Each frame has a small header of 2 to 14 bytes. So a sensor value or an MQTT packet travels with much less overhead than an HTTP request with its headers.

 

Field

Size

Meaning

FIN

1 bit

1 when this frame is the last fragment of a message

RSV1, RSV2, RSV3

3 bits

0 unless an extension defines them

Opcode

4 bits

0x0 continuation, 0x1 text, 0x2 binary, 0x8 close, 0x9 ping, 0xA pong

MASK

1 bit

1 when a Masking-key is present

Payload length

7 bits

0 to 125 is the length itself. 126 means a 16-bit length follows, and 127 means a 64-bit length follows

Masking-key

0 or 4 bytes

Present when MASK is 1

Payload data

variable

Application data, masked when MASK is 1

 

The masking rule has a direction. A client must mask every frame it sends to the server, and a server must never mask the frames it sends to the client. The client XORs the payload with a new 4-byte Masking-key in each frame. This is not encryption, because the key travels in the same frame. Its purpose is to stop a browser from sending bytes that an old proxy could mistake for an HTTP request.

The opcode separates data frames from control frames. MQTT over WebSocket uses binary frames, opcode 0x2, because an MQTT packet is binary. Ping and pong frames check that the connection is still alive. To end the session, one side sends a close frame, the other side answers with its own close frame, and then the TCP connection is closed.

  • The frame header is small : 2 bytes for a short unmasked payload, and at most 14 bytes.
  • Only client frames are masked : the Masking-key protects proxies, and it does not protect the data.
  • MQTT rides in binary frames : each WebSocket message carries MQTT packets that the broker reads as if they came over plain TCP.