← Назад к вопросам

Что такое Websocket?

2.3 Middle🔥 131 комментариев
#REST API и микросервисы#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Что такое WebSocket

Определение

WebSocket — это протокол полнодуплексной коммуникации, который работает поверх TCP и позволяет двусторонний обмен данными в реальном времени между клиентом и сервером без необходимости в polling или long-polling.

Проблема, которую решает WebSocket

HTTP — однонаправленный запрос-ответ

Проблемы HTTP:

  • Для получения обновлений нужно постоянно отправлять запросы (polling)
  • Много сетевого трафика на пустые ответы
  • Высокая задержка в доставке данных от сервера к клиенту

WebSocket — двусторонний постоянный канал

WebSocket решает эти проблемы через постоянное двустороннее соединение.

Как работает WebSocket

Фаза 1: Upgrade (handshake)

Клиент отправляет обычный HTTP запрос с просьбой upgrade на WebSocket:

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

Сервер соглашается:

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

После upgrade TCP соединение остаётся открытым, но теперь используется WebSocket протокол вместо HTTP.

Фаза 2: Двусторонний обмен (frames)

Данные передаются фреймами. Каждый фрейм содержит:

  • FIN — последний ли это фрейм
  • Opcode — тип данных (текст, бинарный, контроль)
  • Mask — маска для безопасности (клиент всегда маскирует)
  • Payload — данные

Фаза 3: Закрытие соединения

Любая сторона может инициировать закрытие, отправив Close фрейм.

Практический пример на Java

Использование Spring WebSocket

import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class ChatWebSocketHandler extends TextWebSocketHandler {
    
    private List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
    
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        sessions.add(session);
        System.out.println("Client connected: " + session.getId());
    }
    
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) 
            throws IOException {
        String payload = message.getPayload();
        System.out.println("Received: " + payload);
        
        // Broadcast сообщение всем клиентам
        for (WebSocketSession s : sessions) {
            if (s.isOpen()) {
                s.sendMessage(new TextMessage(
                    "User " + session.getId() + ": " + payload
                ));
            }
        }
    }
    
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        sessions.remove(session);
        System.out.println("Client disconnected: " + session.getId());
    }
}

Конфигурация

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new ChatWebSocketHandler(), "/ws/chat")
                .setAllowedOrigins("*");
    }
}

Клиентская часть (JavaScript)

const ws = new WebSocket("ws://localhost:8080/ws/chat");

ws.onopen = (event) => {
    console.log("Connected");
    ws.send("Hello from client!");
};

ws.onmessage = (event) => {
    console.log("Message: " + event.data);
};

ws.onclose = (event) => {
    console.log("Disconnected");
};

Использование Java WebSocket API

Server Endpoint

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.*;

@ServerEndpoint("/ws/notification")
public class NotificationEndpoint {
    
    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<>());
    
    @OnOpen
    public void onOpen(Session session) {
        clients.add(session);
        System.out.println("New connection: " + session.getId());
    }
    
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("Message from " + session.getId() + ": " + message);
        
        // Отправить всем клиентам
        for (Session client : clients) {
            if (client.isOpen()) {
                client.getBasicRemote().sendText(message);
            }
        }
    }
    
    @OnClose
    public void onClose(Session session) {
        clients.remove(session);
        System.out.println("Connection closed: " + session.getId());
    }
    
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
}

WebSocket vs HTTP

АспектHTTPWebSocket
НаправлениеОднонаправленныйДвусторонний
ИнициацияТолько клиентОбе стороны
ЗадержкаВысокаяНизкая
ТрафикМного заголовковМинимум
МасштабируемостьХорошаяТребует памяти
КешированиеВстроенноеНет

Когда использовать WebSocket

Используй WebSocket для:

  • Чат приложений
  • Real-time уведомлений
  • Live трансляции данных
  • Совместного редактирования
  • Online игр
  • IoT датчиков

Не используй WebSocket для:

  • Простых REST API запросов
  • Статического контента
  • Когда нужна история запросов и кеширование

Best Practices

  1. Обрабатывай разъединения: Клиент должен иметь логику переподключения при потере соединения

  2. Используй heartbeat для проверки соединения: Сервер отправляет ping каждые 30 секунд

  3. Масштабирование на несколько серверов:

    • Используй Redis Pub/Sub для broadcast между серверами
    • Или используй Message Broker (RabbitMQ, Kafka)
  4. Безопасность:

    • Всегда используй WSS (WebSocket Secure, поверх TLS)
    • Валидируй сообщения
    • Аутентифицируй при подключении

Вывод

WebSocket — это мощный протокол для real-time коммуникации, который кардинально отличается от HTTP своей двусторонней природой. Он идеален для приложений, требующих мгновенного обмена данными между сервером и клиентом.