Spec-Zone.ru › Socket.IO 4

Решение проблем с подключением

Общие/известные проблемы:

  • сокет не может подключиться
  • сокет отключается
  • сокет застрял в HTTP-долговом опросе

Проблема: сокет не может подключиться

Возможные объяснения:

  • Вы пытаетесь подключиться к простому серверу WebSocket
  • Сервер недоступен
  • Клиент несовместим с версией сервера
  • Сервер не отправляет необходимые заголовки CORS
  • Вы не включили "липкие сессии" (в конфигурации с несколькими серверами)

Вы пытаетесь подключиться к простому серверу WebSocket

Как объясняется в разделе "Что Socket.IO не реализует", клиент Socket.IO не является реализацией WebSocket и, следовательно, не сможет установить соединение с сервером WebSocket, даже с transports: ["websocket"].

const socket = io("ws://echo.websocket.org", {
  transports: ["websocket"]
});

Сервер недоступен

Убедитесь, что сервер Socket.IO доступен по указанному URL. Вы можете проверить это с помощью:

curl "<the server URL>/socket.io/?EIO=4&transport=polling"

Результат должен быть примерно таким:

0{"sid":"Lbo5JLzTotvW3g2LAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000}

Если это не так, проверьте, что сервер Socket.IO запущен и нет никаких препятствий для подключения.

Клиент несовместим с версией сервера

Вот таблица совместимости для клиента JS:

Версия JS клиента Версия сервера Socket.IO
1.x 2.x 3.x 4.x
1.x ДА НЕТ НЕТ НЕТ
2.x НЕТ ДА ДА1 ДА1
3.x НЕТ НЕТ ДА ДА
4.x НЕТ НЕТ ДА ДА

[1] Да, при allowEIO3: true

Вот таблица совместимости для клиента Java:

Версия Java клиента Версия сервера Socket.IO
2.x 3.x 4.x
1.x ДА ДА1 ДА1
2.x НЕТ ДА ДА

[1] Да, при allowEIO3: true

Вот таблица совместимости для клиента Swift:

Версия Swift клиента Версия сервера Socket.IO
2.x 3.x 4.x
v15.x ДА ДА1 ДА2
v16.x ДА3 ДА ДА

[1] Да, при allowEIO3: true (сервер) и .connectParams(["EIO": "3"]) (клиент):

SocketManager(socketURL: URL(string:"http://localhost:8087/")!, config: [.connectParams(["EIO": "3"])])

[2] Да, при allowEIO3: true (сервер)

[3] Да, при .version(.two) (клиент):

SocketManager(socketURL: URL(string:"http://localhost:8087/")!, config: [.version(.two)])

Сервер не отправляет необходимые заголовки CORS

Если вы видите следующую ошибку в консоли:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ...

Это, вероятно, означает, что:

  • вы не правильно подключаетесь к серверу Socket.IO (см. выше)
  • вы не включили Cross-Origin Resource Sharing (CORS) на стороне сервера.

См. документацию здесь.

Вы не включили "липкие сессии" (в конфигурации с несколькими серверами)

При масштабировании до нескольких серверов Socket.IO необходимо убедиться, что все запросы от данного сеанса Socket.IO попадают на один и тот же сервер Socket.IO. Объяснение можно найти здесь.

Если этого не сделать, вы получите HTTP 400 ответы с кодом: {"code":1,"message":"Session ID unknown"}

См. документацию здесь.

Проблема: сокет отключается

Прежде всего, обратите внимание, что отключения — распространённое и ожидаемое явление, даже при стабильном интернет-соединении:

  • любой элемент между пользователем и сервером Socket.IO может временно выйти из строя или перезапуститься
  • сам сервер может быть остановлен в рамках политики автоматического масштабирования
  • пользователь может потерять соединение или переключиться с Wi-Fi на 4G, если использует мобильный браузер
  • сам браузер может заблокировать неактивную вкладку

При этом клиент Socket.IO всегда будет пытаться повторно подключиться, если ему не указано иное здесь.

Возможные объяснения отключения:

  • Вкладка браузера была свёрнута, и механизм heartbeat не сработал
  • Клиент несовместим с версией сервера
  • Вы пытаетесь отправить очень большой объём данных

Вкладка браузера была свёрнута, и механизм heartbeat не сработал

Когда вкладка браузера не активна, некоторые браузеры (например, Chrome) ограничивают таймеры JavaScript, что может привести к отключению из-за таймаута heartbeat в Socket.IO v2, поскольку механизм heartbeat полагался на функцию setTimeout на стороне клиента.

В качестве обходного решения можно увеличить значение pingTimeout на стороне сервера:

const io = new Server({
  pingTimeout: 60000
});

Обратите внимание, что обновление до Socket.IO v4 (по крайней мере socket.io-client@4.1.3, из-за этой причины) должно предотвратить подобные проблемы, поскольку механизм heartbeat был изменён (теперь сервер отправляет пакеты PING).

Клиент несовместим с версией сервера

Поскольку формат пакетов, отправляемых через транспорт WebSocket, аналогичен в v2 и v3/v4, вы, возможно, сможете подключиться с несовместимым клиентом (см. выше), но подключение будет закрыто через определённое время.

Таким образом, если у вас происходит регулярное отключение через 30 секунд (что было суммой значений pingTimeout и pingInterval в Socket.IO v2), это, безусловно, связано с несовместимостью версий.

Вы пытаетесь отправить очень большой объём данных

Если вы отключаетесь при отправке очень большого объёма данных, это может означать, что вы достигли значения maxHttpBufferSize, которое по умолчанию равно 1 МБ. Настройте его в соответствии с вашими потребностями:

const io = require("socket.io")(httpServer, {
  maxHttpBufferSize: 1e8
});

Очень большой объём данных, который загружается дольше, чем значение параметра pingTimeout, также может вызвать отключение (поскольку механизм heartbeat завершается неудачно во время загрузки). Настройте его в соответствии с вашими потребностями:

const io = require("socket.io")(httpServer, {
  pingTimeout: 60000
});

Проблема: сокет застрял в HTTP-долговом опросе

В большинстве случаев вы должны увидеть что-то вроде этого:

Network monitor upon success

  1. установление соединения Engine.IO (содержит идентификатор сеанса — здесь, zBjrh...AAAK — используемый в последующих запросах)
  2. запрос установления соединения Socket.IO (содержит значение параметра auth )
  3. ответ на запрос установления соединения Socket.IO (содержит Socket#id)
  4. соединение WebSocket
  5. первый запрос HTTP-долгового опроса, который закрывается после установления соединения WebSocket

Если вы не видите ответа HTTP 101 Switching Protocols для 4-го запроса, это означает, что что-то между сервером и вашим браузером препятствует подключению WebSocket.

Обратите внимание, что это не обязательно блокирует процесс, поскольку подключение всё ещё устанавливается с помощью HTTP-долгового опроса, но это менее эффективный способ.

Вы можете получить имя текущего транспорта с помощью:

Клиентская сторона

socket.on("connect", () => {
  const transport = socket.io.engine.transport.name; // in most cases, "polling"

  socket.io.engine.on("upgrade", () => {
    const upgradedTransport = socket.io.engine.transport.name; // in most cases, "websocket"
  });
});

Серверная сторона

io.on("connection", (socket) => {
  const transport = socket.conn.transport.name; // in most cases, "polling"

  socket.conn.on("upgrade", () => {
    const upgradedTransport = socket.conn.transport.name; // in most cases, "websocket"
  });
});

Возможные причины:

  • прокси перед вашими серверами не принимает подключение WebSocket

Прокси перед вашими серверами не принимает подключение WebSocket

См. документацию здесь.

© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v4/troubleshooting-connection-issues

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API