yvikt
@yvikt
it-шник самоучка

Как работает websocket на низком уровне?

Интересует объяснение работы websocket на низком уровне.
На сколько мне известно, websocket это lightweight wrapper over tcp.
Но вот не до конца понятно что на происходит на сервере.
Ниже я изложу свое представление/предположение того как это работает. Я не специалист в unix tcp/ip and system programming, поэтому мое изложение скорее всего далеко от истины. Я буду использовать понятные для меня термины.
Термины и сокращения: СП-слушающее приложение
Рассчитываю на то, что специалист в данной области сможет понять что я хочу узнать)
Итак, представим что сервер, скажем Nginx, слушает 80 порт, что подразумевает передачу байтов данных между ним и клиентом. После установления обычного tcp соединения и "переговоров" Upgrade: WebSocket Connection: Upgrade (по сути обмен текстовой информацией между клиентом и сервером) создается ws-соединение.
Вопрос 1
Браузер инициирует новое tcp соединение на тот же 80 порт сервера или бывают случаи что на другой ?
Вопрос 2
Что сервер делает с ws пакетами - проксирует их к СП как есть в обертке, или же обертку раскрывает и передает "чистые/сырые" данные далее ?
Вопрос 3
Как сервер отличает ws от http - по некой сигнатуре - типа по последовательности первых пришедших байт, по которым можно распознать что это именно ws а не http ?
Вопрос 4
Как эти данные передаются в сторону СП - через переменные окружения, или через unix-socket или через tcp стек?
Если используя последние два варианта, то получается что сервер держит внутри системы соединения с СП до тех пор пока "наружное" tcp соединение между клиентом и сервером не буде закрыто?
Вопрос 5
В свою очередь СП это отдельный unix процесс отличный от основного бекенд приложения, которое работает по принципу "спросили - запустился - обработал - сформировал ответ - отправил - завершился" Или же это все то же бекенд приложение только в том случае если с ним установлено ws-соединение, оно не прекращает свою работу?
  • Вопрос задан
  • 4612 просмотров
Пригласить эксперта
Ответы на вопрос 3
bingo347
@bingo347
Crazy on performance...
Вопрос 1
Браузер инициирует новое tcp соединение на тот же 80 порт сервера или бывают случаи что на другой ?
WebSocket работает не поверх голого tcp, а поверх http (а тот уже поверх tcp или tls -> tcp). 80 порт стандартный для http, а 443 - для https (http поверх tls). WebSocket по умолчанию использует те же 80 и 443 порты для ws и wss протоколов соответственно. Но никто не мешает использовать кастомный порт. Конкретные порты для конкретных протоколов - это не более соглашения. Порты работают на IP уровне, который ничего не знает о прикладном уровне.

Вопрос 2
Что сервер делает с ws пакетами - проксирует их к СП как есть в обертке, или же обертку раскрывает и передает "чистые/сырые" данные далее ?
Если речь идет о nginx как о реверси прокси, то для него это обычный http запрос, просто клиент очень долго шлет тело запроса, а сервер тело ответа (главное таймауты тут выключить). Так как http в принципе не запрещает серверу начать слать ответ не закончив чтение запроса, все вполне прекрасно работает.

Вопрос 3
Как сервер отличает ws от http - по некой сигнатуре - типа по последовательности первых пришедших байт, по которым можно распознать что это именно ws а не http ?
По http заголовкам. В частности клиент шлет заголовок upgrade в котором говорит, что хочет WebSocket и еще несколько специфичных для WebSocket заголовков, а сервер отвечает статусом 101 и своим набором заголовков. Это и есть WebSocket рукопожатие. Само общение происходит уже в теле запроса и теле ответа.

Вопрос 4
Как эти данные передаются в сторону СП - через переменные окружения, или через unix-socket или через tcp стек?
Если используя последние два варианта, то получается что сервер держит внутри системы соединения с СП до тех пор пока "наружное" tcp соединение между клиентом и сервером не буде закрыто?
На уровне tcp вообще пофиг сколько времени открыто соединение, какая из сторон в какой последовательности и сколько данных отправляет. Тут лишь то, что клиент может попробовать открыть соединение, сервер его может принять (или отклонить), а после любая из сторон может слать данные другой или закрыть соединение. Ну и плюс есть гарантии, что потерянные данные будут отправлены повторно и порядок получения совпадет с порядком отправки. На уровне http у нас обычный запрос-ответ, просто клиент слишком долго шлет тело запроса, а сервер - тело ответа. На уровне WebSocket у нас в обе стороны ходят MessageFrame'ы, содержащие данные + метаданные и имеющие четкие границы.

Вопрос 5
В свою очередь СП это отдельный unix процесс отличный от основного бекенд приложения, которое работает по принципу "спросили - запустился - обработал - сформировал ответ - отправил - завершился" Или же это все то же бекенд приложение только в том случае если с ним установлено ws-соединение, оно не прекращает свою работу?
Как реализуете, так и будет. Но одно можно сказать точно, соединение должно быть открытым на протяжении всего сеанса обмена сообщениями.
Важно еще понимать, что в контексте WebSocket нет понятий запрос и ответ (хотя их могут реализовывать нижележащие протоколы), есть лишь понятие сообщение. Каждая из сторон, пока открыто соединение, может в любой момент времени отправлять любое количество сообщений.

P.S. если обе стороны (и клиент и сервер) не ограничены только http протоколом для общения через tcp (как например это происходит у браузерных приложений), то WebSocket будет лишней нагрузкой как на сеть, так и на вычисления. Лучше взять какой-нибудь бинарный сериализатор, с четкими границами (msgpack, flatbuffer) и гонять данные по raw tcp или tls.
Ответ написан
Ответ на этот и многие другие вопросы в RFC 6455
https://tools.ietf.org/html/rfc6455
Ответ написан
Комментировать
yvikt
@yvikt Автор вопроса
it-шник самоучка
Большое спасибо за развернутый ответ.
Для меня стало открытием что ws не работает без http, т.е. только поверх.
Я почему-то думал что после переговоров, клиент и сервер переходят на чистый TCP (почти чистый, учитывая что ws обертка легковесная). Вот почему мне было непонятно, как после переговоров веб сервер идентифицирует и проксирует "новоустановленное" (как я думал) TCP соединение.
А все оказывается намного проще )
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы