Conceitos
Conexões persistentes bidirecionais (WebSocket)
Intuição
Imagine que você quer saber se chegou novidade e, para isso, liga de tempos em tempos para o outro lado, se apresenta por completo a cada ligação e ouve a resposta antes de desligar. É cansativo, e o outro lado só consegue falar quando você pergunta. A alternativa é fazer uma única ligação e deixá-la aberta: a partir daí qualquer um dos dois fala quando tiver algo a dizer, e há uma forma combinada de avisar que vai desligar.
Como funciona
O RFC 6455 parte do custo de simular comunicação bidirecional sobre HTTP: polling repetido, uma conexão TCP para o servidor enviar e uma nova para cada mensagem do cliente, o overhead dos cabeçalhos HTTP completos em cada mensagem do cliente para o servidor e o trabalho do script de casar cada requisição com a resposta correspondente. O WebSocket troca isso por uma única conexão TCP que carrega o tráfego nos dois sentidos, formada por um handshake de abertura seguido de uma camada fina de framing de mensagens. O handshake é uma requisição GET HTTP comum, o que permite atravessar infraestrutura que já entende HTTP, com os cabeçalhos Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Version 13 e um Sec-WebSocket-Key aleatório; se o servidor aceita, responde 101 Switching Protocols com um Sec-WebSocket-Accept derivado da chave (GUID fixo concatenado, SHA-1, base64), e a mesma conexão TCP passa a carregar frames WebSocket em vez de HTTP. Daí em diante cada lado envia mensagens quando quiser, em frames de texto ou binário que podem ser fragmentados, e todo frame do cliente para o servidor deve ser mascarado com uma chave imprevisível, para que um script não controle os bytes que vão pela rede e envenene um proxy intermediário. O Ping (que o receptor deve responder com um Pong repetindo os dados, a menos que já tenha recebido um Close) pode servir de keepalive ou para checar se o outro lado ainda responde. O fechamento também é por mensagem: quem quer encerrar envia um frame Close com código de status opcional (como 1000, fechamento normal), não envia mais dados depois disso, e o par responde com o seu próprio Close, caso ainda não tenha enviado um; quando os dois lados enviaram e receberam Close, o servidor deve fechar o TCP imediatamente. No modelo de origin, o navegador sempre envia o cabeçalho Origin, e o servidor que só quer atender certos sites deve, em regra, compará-lo com as origins esperadas e, se a origin não for aceitável, responder 403. Isso barra scripts maliciosos num navegador confiável, mas não prova quem chama, porque um cliente que não é navegador pode colocar qualquer valor em Origin; confidencialidade e integridade vêm de rodar sobre TLS (URIs wss), e a autenticação de cliente fica a cargo dos mecanismos que um servidor HTTP comum usaria.
Na prática
O RFC apresenta o WebSocket como substituto mais simples do polling HTTP quando uma aplicação de navegador precisa trocar dados com o servidor nos dois sentidos, evitando várias conexões por cliente e cabeçalhos HTTP completos a cada mensagem do cliente. Na prática, vale usar wss para ter TLS, validar o Origin do handshake mas tratá-lo só como proteção contra scripts em navegadores e não como autenticação, usar Ping/Pong como keepalive e encerrar sempre com o handshake de Close e um código de status adequado. Como o handshake é uma requisição HTTP, a conexão pode atravessar infraestrutura que já entende HTTP antes de virar WebSocket.
Use em um desenho
Pratique na escola de System Design os casos que dependem deste conceito.