Причины отказа подключения клиента

Обычно клиентский отказ подключения имеет два типа ошибок: connection refuse (отказ соединения) и connection timeout (время ожидания подключения).

Отказ соединения (connection refuse)

Обычно причины следующие:

  1. Неправильный порт подключения клиента
  2. Неправильный домен или IP-адрес, к которому пытается подключиться клиент
  3. Если клиент использует доменное имя для подключения, то оно может указывать на неправильный IP-адрес сервера
  4. Использование сервером cdn или другого ускорителя, что приводит к несоответствию фактического IP-адреса подключения и ожидаемого IP-адреса
  5. Сервер не запущен или порт не прослушивается
  6. Использование программного обеспечения для сетевого прокси
  7. IP-адрес, на который прослушивается сервер, не совпадает с адресом доступа. Например, если сервер прослушивает 127.0.0.1, то клиент может подключаться только через 127.0.0.1 и не может подключаться через локальный IP или внешний IP. Рекомендуется установить прослушивание адреса как 0.0.0.0, чтобы иметь возможность подключения через localhost, локальную сеть и внешний IP.

Время ожидания подключения (connection timeout)

Обычные причины:

  1. Ограничение подключений серверного брандмауэра, можно попробовать временно отключить брандмауэр
  2. В случае облачного сервера, защита доступа также может блокировать установку соединения, требуется открытие соответствующего порта в панели управления
  3. Если используется панель управления типа Baota, необходимо открыть соответствующий порт.
  4. Сервер не существует или не запущен
  5. Если клиент использует доменное имя для подключения, то оно может указывать на неправильный IP-адрес сервера
  6. IP-адрес, к которому обращается клиент, является внутренним IP-адресом сервера, и клиент и сервер находятся в разных локальных сетях

cannot assign requested address (не удается назначить запрошенный адрес)

При подключении в качестве клиента, для каждого установления соединения потребляется временный локальный порт. В один момент времени сервер по умолчанию имеет доступные временные порты примерно от 20 000 до 30 000. Если количество подключений к конкретному серверу превысит это значение, то не будет возможности назначить доступный порт, и появится данная ошибка.
Можно увеличить количество временных портов, изменив параметр ядра /etc/sysctl.conf в net.ipv4.ip_local_port_range, например, установить его в 10000 65535 (диапазон временных портов увеличивается до 55 535), после чего выполнить sysctl -p для вступления изменений в силу.
Кроме того, разрыв соединения также приведет к состоянию TIME_WAIT, который будет занимать соответствующий локальный порт в течение некоторого времени, то есть в течение короткого времени большое количество (больше 20-30 тысяч) коротких соединений также может привести к ошибке Cannot assign requested address. В этом случае можно установить быстрое высвобождение TIME_WAIT ядра для решения проблемы, см. оптимизация ядра.

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

Другие ошибки

Если произошла другая ошибка, отличная от connection refuse и connection timeout, то, как правило, причина следующая:

1. Использование клиентом протокола связи, отличного от протокола сервера.
Например, сервер использует протокол связи HTTP, а клиент пытается использовать протокол связи WebSocket - в этом случае соединение невозможно. Если клиент использует протокол связи WebSocket, то сервер также должен использовать протокол связи WebSocket. Если сервер работает на протоколе HTTP, то клиент должен использовать протокол связи HTTP.

Это аналогично ситуации, когда для общения с англичанином необходимо использовать английский язык и японцем - японский язык. Здесь язык аналогичен протоколу связи, обе стороны (клиент и сервер) должны использовать одинаковый язык общения, чтобы обмен был возможен, в противном случае связь невозможна.

Частые ошибки, обусловленные несовпадением протокола связи:

WebSocket connection to 'ws://xxx.com:xx/' failed: Error during WebSocket handshake: Unexpected response code: xxx

WebSocket connection to 'ws://xxx.com:xx/' failed: Error during WebSocket handshake: net::ERR_INVALID_HTTP_RESPONSE

Решение:
Из приведенных выше ошибок видно, что клиент использует соединение ws по протоколу WebSocket. Сервер также должен быть настроен для протокола WebSocket, вот примеры соответствующего кода для части прослушивания.

Если это gatewayWorker, то код для прослушивания будет следующим:

// протокол WebSocket, таким образом, клиент может подключиться по ws://...; xxxx - это порт, который не требует изменения
$gateway = new Gateway('websocket://0.0.0.0:xxxx');

Если это Workerman, то код будет таким:

// протокол WebSocket, таким образом, клиент может подключиться по ws://...; xxxx - это порт, который не требует изменения
$worker = new Worker('websocket://0.0.0.0:xxxx');