These are my own notes from reading [The Websocket Protocol](https://datatracker.ietf.org/doc/html/rfc6455) specification. Here I will just note down things I think I may forget or just want to have in writing for future reference. The protocol consists of an opening handshake followed by message framing layered over [[TCP]]. It is state the the goal of the protocol is to not have to rely on opening multiple [[HTTP]] connections like using [[XMLHttpRequest]], iframes, and [[Long polling]]. ## Protocol Overview The protocol consists of two parts: a handshake and the data transfer. The client initiates a handshake with: ``` GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 ``` The server may then respond with: ``` HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat ``` A websocket message does not correspond to any network layer framing. The message may be split or coalesced by intermediary transports. Frames have a type. Each frame belong to the same message contains the same type of data. The different types of frames are: - Textual data interpreted as [[UTF-8]] - Binary data - Control frames for protocol-level signaling ### Completing the handshake The server has to prove that it has received the handshake. It does so by: 1. Pick out the `Sec-WebSocket-Key` header of the request 2. Concatenate it with the value `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`. 1. This value is globally unique 3. Take the [[SHA-1]] hash of the concatenated value 4. [[Base64]] encode the hash 5. Return back to client in the `Sec-WebSocket-Accept` header Example: ```go // 1. Pick out the `Sec-WebSocket-Key` header of the request secWebsocketKey := "dGhlIHNhbXBsZSBub25jZQ==" // 2. Concatinate concatenated := secWebsocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" // 3. SHA-1 hash hash := sha1.Sum(concatenated) // 4. Base64 encode b64 := base64.EncodeToString(hash) // 5. Send back response // ... ```