linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Сеть: L4 и выше/websocket

kb/network-l4 ── Сеть: L4 и выше ── intermediate

WebSocket - bidirectional поверх HTTP

WebSocket - двусторонний канал поверх одного TCP. Апгрейд из HTTP/1.1 через Upgrade header, потом обмен бинарными frame'ами. Используется для real-time UI - чаты, дашборды, live-обновления.

view as markdownaka: websockets, ws-protocol, websocket-upgrade

Зачем WebSocket

HTTP - request/response, сервер не может «толкнуть» обновление сам. До WebSocket'а делали polling (запрос каждые 5 сек) или long-polling. Это тратит CPU и каналы. WebSocket даёт одно TCP-соединение, через которое и клиент, и сервер шлют сообщения когда захотят.

Применение в LinuxLab: WebSocket на /api/ws/sessions/{id} - PTY для терминала + state-updates от агента в контейнере.

Handshake

Начинается как обычный [[http-protocol|HTTP/1.1]] запрос с upgrade:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

Сервер отвечает 101 Switching Protocols:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

Sec-WebSocket-Accept = base64(SHA1(client_key + magic_GUID)). Это не безопасность, а защита от случайного апгрейда того, что не понимает WebSocket.

После 101 - тот же TCP-сокет, но протокол поменялся: дальше идут бинарные WebSocket-frame'ы, не HTTP.

Frame format

 0   1   2   3   4   5   6   7
+-+-+-+-+---+---+-+-+---+---+----+
|F|R|R|R| op|M| payload-len  |...|
|I|S|S|S|cod|A|              |   |
|N|V|V|V|e  |S|              |   |
| |1|2|3|   |K|              |   |
+-+-+-+-+---+-+-+--------------+
  • FIN - последний frame в логическом message? (можно фрагментировать)
  • opcode - 0x1 text, 0x2 binary, 0x8 close, 0x9 ping, 0xA pong
  • MASK - клиент → сервер обязан маскировать payload XOR-ом, сервер → клиент не маскирует
  • payload-len - 7 / 16 / 64 бит (extended если > 125)

Маскирование с клиента нужно для защиты от cache-poisoning старых HTTP-прокси.

ws:// vs wss://

  • ws:// - голый TCP, порт 80
  • wss:// - TLS-обёрнут, порт 443

В проде используем wss:// всегда. WebSocket-handshake живёт внутри [[tls-handshake|TLS-сессии]] - с виду как HTTPS-запрос, апгрейд внутри шифрованного канала.

Ping / Pong

Чтобы убедиться, что соединение живо (NAT не закрыл, peer не упал), стороны шлют ping-frame (opcode 0x9). Получатель обязан вернуть pong (0xA) с тем же payload. Если pong не приходит за N секунд - соединение протухло, реконнект.

Стандартный интервал: 30-60 секунд (короче чем NAT-timeout, обычно 5 минут на UDP-NAT и 2 часа на TCP-NAT).

Close

Корректное закрытие - close-frame (0x8) с 2-байтным status code:

КодЧто
1000normal closure
1001going away (страница закрыта)
1002protocol error
1003unsupported data
1006abnormal closure (не приходит явно, означает «соединение разорвано»)
1011server error
4000+application-defined

Хорошая клиентская реализация на 1006 делает экспоненциальный реконнект.

Backpressure

WebSocket не имеет нативного flow-control на уровне сообщений (только TCP-window). Если сервер шлёт быстрее чем клиент жуёт - буфер растёт. На больших нагрузках надо либо application-level backpressure (acks от клиента), либо drop-message политика.

Размер сообщения

Технически до 2^63 байт. Реально - сервера ставят лимит 1-16 MB. Большие файлы лучше через HTTP, не через WS.

Когда что-то пошло не так

  • Connection closed before handshake - reverse-proxy не пропустил Upgrade header. В nginx нужен proxy_set_header Upgrade $http_upgrade;
  • 1006 каждые 60 сек - load balancer закрывает idle. Нужен ping или конфиг LB на больший timeout
  • Stuck after 1 message - клиент забыл MASK, сервер дропнул
  • Memory growth - нет backpressure, медленные клиенты копят buffer
  • Echo обратный к серверу - забыли валидацию Origin header, cross-site WebSocket hijacking

§ команды

bash
curl -i -N -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGVzdA==' http://localhost:8080/ws

Поднять минимальный WebSocket-handshake руками - увидеть 101 ответ

bash
tcpdump -i any -nn -A 'tcp port 80' | grep -A2 -i 'upgrade'

Поймать WebSocket upgrade в plain text. Для wss:// - не получится без mitm

bash
ss -tnH | grep ':443' | wc -l

Сколько активных TLS-соединений (включая wss://) сейчас держится

bash
wscat -c wss://echo.websocket.org

Простой WebSocket-клиент в shell (npm i -g wscat); шлёшь сообщение - получаешь эхо

§ см. также

  • http-protocolHTTP/1.1, HTTP/2, HTTP/3HTTP/1.1 - текстовый протокол с keep-alive. HTTP/2 - бинарный с мультиплексированием в одном TCP-соединении. HTTP/3 = HTTP/2-семантика поверх QUIC/UDP без TCP-head-of-line blocking.
  • tcp-handshakeTCP three-way handshakeTCP-соединение открывается тремя пакетами: SYN от клиента, SYN-ACK от сервера, ACK от клиента. После - соединение Established, можно слать данные.
  • tls-handshakeTLS handshakeTLS - слой шифрования поверх TCP. Перед передачей данных стороны делают handshake: обмениваются ключами, проверяют сертификат, выбирают cipher.
  • portПорт - как несколько сервисов делят один IP16-битное число (0-65535), идентифицирует **процесс-получатель** на хосте. IP говорит куда (хост), порт - кому (процессу). 80 - HTTP, 443 - HTTPS, 22 - SSH.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки