Причины неудачного подключения клиента
При неудачном подключении клиента могут возникнуть две основные ошибки: connection refuse и connection timeout.
connection refuse (подключение отклонено)
Это обычно происходит по следующим причинам:
- Неправильный порт, используемый клиентом для подключения.
- Неправильный домен или IP-адрес, к которому обращается клиент.
- Если клиент использует домен для подключения, возможно, он указывает на неправильный IP-адрес сервера.
- Сервер использует CDN или другие прокси-сервисы, что приводит к несоответствию фактического IP-адреса с ожидаемым.
- Сервер не запущен или на порту нет прослушивания.
- Используется сетевое программное обеспечение для прокси.
- IP-адрес, на котором сервер слушает, и адрес, по которому происходит доступ, не находятся в одной подсети. Например, если сервер слушает на 127.0.0.1, клиент может подключиться только через 127.0.0.1, а не через локальный или внешние IP-адреса. Рекомендуется установить адрес прослушивания на 0.0.0.0, чтобы локальные, внутренние и внешние соединения могли подключаться.
connection timeout (тайм-аут подключения)
Это обычно происходит по следующим причинам:
- Брандмауэр сервера блокирует подключение; можно временно отключить брандмауэр для проверки.
- Если это облачный сервер, группы безопасности также могут блокировать установление соединения; необходимо открыть соответствующий порт в административной панели.
- Если используется панель управления, такая как宝塔, необходимо открыть соответствующий порт в панеле.
- Сервер не существует или не запущен.
- Если клиент использует домен для подключения, возможно, он указывает на неправильный IP-адрес сервера.
- IP-адрес, к которому обращается клиент, является внутренним IP-адресом сервера, и клиент и сервер находятся не в одной локальной сети.
cannot assign requested address (невозможно назначить запрашиваемый адрес)
В качестве клиента каждое инициированное соединение требует использования временного локального порта. На одном сервере по умолчанию доступно примерно 20-30 тысяч временных портов. Если количество соединений, инициированных к определенному серверу, превышает это значение, то не удается выделить доступный порт, что приводит к этой ошибке.
Можно увеличить количество локальных временных портов, изменив параметр ядра в файле /etc/sysctl.conf в строке net.ipv4.ip_local_port_range, например, установив на 10000 65535 (это увеличит количество локальных портов до 55535), затем выполните 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-протокол, часть кода сервера должна явно указывать протокол 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');