{"id":38,"date":"2024-02-13T14:17:10","date_gmt":"2024-02-13T11:17:10","guid":{"rendered":"http:\/\/caitiem.com\/?p=38"},"modified":"2024-02-13T15:28:35","modified_gmt":"2024-02-13T12:28:35","slug":"a-websocket-primer","status":"publish","type":"post","link":"http:\/\/www.caitiem.com\/2013\/12\/02\/a-websocket-primer\/","title":{"rendered":"A WebSocket Primer"},"content":{"rendered":"\n
Over the past year, prior to leaving 343, I spent a large amount of time working with the WebSockets protocol and upgrading the Halo Services to support it.\u00a0 In order to solidify my knowledge and provide a handy refresher for when this information invariably gets context switched out of my brain in the future, I decided to write a primer on WebSockets.\u00a0 Hopefully other people will find the introduction to this new protocol useful as well.<\/p>\n\n\n\n
In December 2011 the IETF standardized the WebSocket protocol.\u00a0 Unlike the typical Request\/Response messaging patterns provided by HTTP, this network protocol provides a full-duplex communication channel between a host and a client over TCP.\u00a0 This enables server sent events, reactive user experiences, and real time components.<\/p>\n\n\n\n
The WebSocket protocol provides some advantages over the traditional HTTP protocol. Once the connection has been established, there is a point to point system of communication where both devices can communicate with one another simultaneously. This enables server sent events without using a work around like Comet or Long Polling. While these technologies work well, they carry the overhead of HTTP, whereas WebSocket frames have a wire-level overhead of as little as two bytes per frame. The full-duplex communication and low packet overhead make it an ideal protocol for real-time low latency experiences.<\/p>\n\n\n\n
An important note:\u00a0 The WebSocket protocol is not layered on top of HTTP, nor is it an extension of the HTTP protocol.\u00a0 The WebSocket protocol is a light weight protocol layered onto of TCP.\u00a0 The only part HTTP plays is in establishing a WebSocket connection via the HTTP Upgrade request.\u00a0 Also the HTTP Upgrade request is not specific to WebSockets but can be used to support other hand-shakes or upgrade mechanisms which will use the underlying TCP connection.<\/p>\n\n\n\n
A client can establish a WebSocket connection by initiating a client handshake request. As mentioned above the HTTP Upgrade request is used to initiate a WebSocket connection.<\/p>\n\n\n\n
If all goes well on the server and the request can be accepted then the server handshake will be returned.<\/p>\n\n\n\n If an error occurs and the server cannot accept the request, than a HTTP 500 should be returned to indicate that the request has failed and that the protocol is still HTTP.<\/p>\n\n\n\n Once the client server handshake is completed the TCP connection used to make the initial HTTP request has now been upgraded to a WebSocket connection. Messages can now be sent from either the client to the server or the server to the client.<\/p>\n\n\n\n As a developer most of the nuances of the WebSocket handshake are hidden away by the platform specific APIs and SDKs.\u00a0 In the .NET world Windows 8 and Windows Server 2012 introduced native support for the WebSocket protocol. \u00a0In addition Internet Explorer 10 introduced native support for the WebSocket protocol as well. Also a variety of other platforms\u00a0support WebSockets.<\/p>\n\n\n\n Using the .NET 4.5 Framework the client code to establish a WebSocket connection in C# would look like this. ClientWebSocket webSocket = null; webSocket = new ClientWebSocket(); await webSocket.ConnectAsync(new Uri(“ws:\/\/localhost\/Echo”), CancellationToken.None);<\/p>\n\n\n\n Once the connection succeeds on the client the ClientWebSocket object can be used to receive and send messages.<\/p>\n\n\n\n Using the .Net 4.5 Framework on a simple server using HttpListener, the C# code to accept a WebSocket request and complete the hand-shake would look like this. HttpListenerContext listenerContext = await httpListener.GetContextAsync(); if (listenerContext.Request.IsWebSocketRequest) { WebSocketContext webSocketContext = await listenerContext.AcceptWebSocketAsync(); WebSocket webSocket = webSocketContext.WebSocket } else { \/\/Return a 426 – Upgrade Required Status Code listenerContext.Response.StatusCode = 426; listenerContext.Response.Close(); }<\/p>\n\n\n\nGET \/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<\/code><\/p>\n\n\n\nHTTP\/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=<\/code><\/p>\n\n\n\nCode<\/strong><\/h3>\n\n\n\n
Client<\/h4>\n\n\n\n
Server<\/h4>\n\n\n\n