Razones para la conexión fallida del cliente
Generalmente, cuando la conexión falla, el cliente puede mostrar dos tipos de errores: connection refuse y connection timeout.
connection refuse (Conexión rechazada)
Generalmente, las razones son las siguientes:
- El puerto al que se conecta el cliente es incorrecto.
- El nombre de dominio o la IP a la que se conecta el cliente son incorrectos.
- Si el cliente usa un nombre de dominio para conectarse, es posible que el dominio apunte a una IP de servidor incorrecta.
- El servidor está usando CDN o proxy de aceleración, lo que hace que la IP real a la que se conecta no coincida con la IP esperada.
- El servidor no ha sido iniciado o el puerto no está en escucha.
- Se está utilizando un software de proxy de red.
- La IP en la que escucha el servidor y la dirección de acceso no están en el mismo rango. Por ejemplo, si el servidor escucha en 127.0.0.1, el cliente solo puede conectarse a través de 127.0.0.1, no podrá conectarse a través de una IP de red local o externa. Se recomienda configurar la dirección de escucha como 0.0.0.0, de esta manera tanto la máquina local, la red local como la red externa pueden conectarse.
connection timeout (Tiempo de conexión agotado)
Generalmente, las razones son las siguientes:
- El firewall del servidor está bloqueando la conexión; se puede intentar desactivar temporalmente el firewall.
- Si se trata de un servidor en la nube, el grupo de seguridad también puede estar bloqueando la conexión, por lo que se requiere abrir el puerto correspondiente en el panel de administración.
- Si se usa un panel como 宝塔, se debe abrir el puerto correspondiente en dicho panel.
- El servidor no existe o no ha sido iniciado.
- Si el cliente utiliza un nombre de dominio para conectarse, es posible que el dominio apunte a una IP de servidor incorrecta.
- La IP a la que accede el cliente es una IP interna del servidor, y el cliente y el servidor no están en la misma red local.
cannot assign requested address (No se puede asignar la dirección solicitada)
Como cliente, cada vez que se inicia una conexión, necesita ocupar un puerto temporal local. Un servidor por defecto tiene disponibles entre 20.000 y 30.000 puertos temporales. Si el número de conexiones que se intenta establecer hacia un servidor específico excede este valor, no se podrá asignar un puerto disponible, y se generará este error.
Se puede aumentar la cantidad de puertos temporales locales cambiando el parámetro del núcleo en /etc/sysctl.conf modificando net.ipv4.ip_local_port_range, por ejemplo, configurándolo como 10000 65535 (esto aumentará el rango de puertos locales a 55535). Para aplicar los cambios, se puede ejecutar sysctl -p.
Además, después de que una conexión se cierra, esta entra en estado TIME_WAIT y seguirá utilizando el puerto local correspondiente durante un tiempo determinado. Así que, si se inician muchas conexiones cortas (excediendo 20.000 a 30.000) en poco tiempo, también se generará el error Cannot assign requested address. En este caso, se puede resolver configurando el núcleo para reciclar rápidamente TIME_WAIT; ver Optimización del núcleo.
Nota
El límite en la cantidad de puertos locales solo se aplica al cliente; el servidor no tiene un límite en los puertos locales. Siempre que haya suficientes recursos, la cantidad de conexiones que puede mantener el servidor puede considerarse como ilimitada.
Otros errores
Si el error que ocurre no es connection refuse ni connection timeout, generalmente se debe a las siguientes razones:
1. El protocolo de comunicación que usa el cliente no coincide con el del servidor.
Por ejemplo, si el servidor utiliza el protocolo de comunicación http, el cliente que accede utilizando el protocolo websocket no podrá conectarse. Si el cliente se conecta usando el protocolo websocket, el servidor también debe usar el protocolo websocket. Si el servidor es un servicio del protocolo http, entonces el cliente debe acceder usando el protocolo http.
El principio aquí es similar a hablar con un británico: se necesita usar inglés. Si se desea hablar con un japonés, se necesita utilizar japonés. En este caso, el lenguaje representa el protocolo de comunicación, y ambos lados (el cliente y el servidor) deben usar el mismo lenguaje para comunicarse; de lo contrario, no podrán comunicarse.
Los errores comunes provocados por la discrepancia en el protocolo de comunicación incluyen:
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
Solución:
A partir de los errores mencionados anteriormente, se puede inferir que el cliente está usando una conexión ws, lo que indica el protocolo websocket. El servidor también necesita ser del protocolo websocket para poder comunicarse. El código del servidor que escucha necesita especificar el protocolo websocket para que la comunicación funcione, como se muestra a continuación.
Si es un gatewayWorker, el código de escucha es similar a:
// protocolo websocket, de esta manera el cliente puede conectarse usando ws://... . xxxx es el puerto que no necesita cambiar.
$gateway = new Gateway('websocket://0.0.0.0:xxxx');
Si es Workerman, entonces es:
// protocolo websocket, de esta manera el cliente puede conectarse usando ws://... . xxxx es el puerto que no necesita cambiar.
$worker = new Worker('websocket://0.0.0.0:xxxx');