На каком уровне модели OSI работает протокол WebSocket

Ответ

Протокол WebSocket работает на прикладном уровне (L7) модели OSI, так же как HTTP, FTP или SMTP.

Он функционирует поверх TCP (транспортный уровень, L4), используя его для надежной доставки данных.

Ключевая особенность WebSocket — установление соединения через стандартный HTTP-запрос с заголовком Upgrade: websocket. После успешного "рукопожатия" HTTP-соединение "повышается" до постоянного полнодуплексного TCP-соединения. Это позволяет клиенту и серверу обмениваться данными в обе стороны в реальном времени без необходимости постоянно отправлять новые HTTP-запросы.

Пример сервера на Python и клиента на JavaScript:

Сервер (Python, websockets):

import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        print(f"< {message}")
        response = f"Эхо: {message}"
        await websocket.send(response)
        print(f"> {response}")

start_server = websockets.serve(echo, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Клиент (JavaScript, в браузере):

const socket = new WebSocket('ws://localhost:8765');

socket.onopen = function(e) {
  console.log("[open] Соединение установлено");
  socket.send("Привет, WebSocket!");
};

socket.onmessage = function(event) {
  console.log(`[message] Получены данные: ${event.data}`);
};

socket.onclose = function(event) {
  console.log('[close] Соединение закрыто');
};

Ответ 18+ 🔞

Давай разберёмся, что это за зверь такой — WebSocket. Ну, ты знаешь, как обычно: открыл страницу, она там запросила что-то у сервера, получила ответ и всё. Как будто в дверь постучал, тебе передали записку и закрыли. А хочется-то, чтобы дверь осталась открытой и можно было болтать без остановки, да? Вот для этого и придумали WebSocket, ёпта.

Так вот, этот протокол работает на прикладном уровне (L7) — прямо как наш старый знакомый HTTP, или тот же FTP для файлов. Но вся его магия в том, что он не тупо стучится каждый раз, а делает хитрый финт ушами. Сначала он прикидывается обычным HTTP-запросом, такой скромный, с заголовком Upgrade: websocket. Сервер, если не мудак, отвечает: "Ага, давай, повышаем!" И после этого рукопожатия — пиздец, обычное HTTP-соединение превращается в постоянное, полноценное TCP-соединение. И пошло-поехало: данные туда-сюда летят в реальном времени, без этих дурацких перезапросов каждую секунду. Красота же, блядь!

Ну а теперь, чтобы не быть голословным, вот тебе пример, как это выглядит в коде. Смотри, не зевай.

Сервер (Python, websockets):

import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        print(f"< {message}")
        response = f"Эхо: {message}"
        await websocket.send(response)
        print(f"> {response}")

start_server = websockets.serve(echo, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

Клиент (JavaScript, в браузере):

const socket = new WebSocket('ws://localhost:8765');

socket.onopen = function(e) {
  console.log("[open] Соединение установлено");
  socket.send("Привет, WebSocket!");
};

socket.onmessage = function(event) {
  console.log(`[message] Получены данные: ${event.data}`);
};

socket.onclose = function(event) {
  console.log('[close] Соединение закрыто');
};

Вот и вся история. Запустил сервак, открыл страничку в браузере — и понеслась душа в рай. Сообщения летят туда-обратно, как будто разговариваешь, а не как с тем же HTTP, где каждое слово — это новый запрос, новый ответ. Удобно, ёпта, особенно для всяких чатов, уведомлений или онлайн-игрушек. Просто иногда диву даёшься — ну почему раньше до этого не додумались, а?