클라이언트 연결 실패 원인

일반적으로 연결 실패한 클라이언트는 "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으로 변경하여 로컬, 내부, 외부 모두 접속할 수 있도록 권장됩니다.

connection timeout(연결 시간 초과)

일반적으로 다음과 같은 이유로 발생합니다:

  1. 서버 방화벽이 연결을 차단한 경우, 임시로 방화벽을 닫아보세요.
  2. 클라우드 서버인 경우, 보안 그룹이 연결을 차단할 수 있으므로 관리 대시보드에서 해당 포트를 열어야 합니다.
  3. Baota 등 패널을 사용하는 경우, 해당 포트를 Baota에서 열어야 합니다.
  4. 서버가 존재하지 않거나 실행되지 않는 경우
  5. 클라이언트가 도메인을 통해 연결하는 경우, 도메인이 잘못된 서버 IP를 가리키고 있는 경우
  6. 클라이언트가 서버의 내부 IP에 연결하고 있으며 클라이언트와 서버가 같은 로컬 네트워크에 없는 경우

cannot assign requested address(요청된 주소를 할당할 수 없음)

클라이언트로서 각 연결을 시작할 때마다 로컬에서 임시 포트를 사용해야 합니다. 한 서버당 기본적으로 2-3 만 개의 임시 포트를 사용할 수 있으며, 특정 서버로의 연결 수가 이 값을 초과하면 사용 가능한 포트를 할당할 수 없어 이 오류가 발생합니다. 임시 포트 수를 늘리기 위해 /etc/sysctl.conf에서 net.ipv4.ip_local_port_range를 변경할 수 있으며, 예를 들어 10000 65535로 설정하여 로컬 포트 수를 늘릴 수 있습니다. 또한 연결이 종료된 후에도 해당 로컬 포트를 일정 시간 동안 계속 사용하기 때문에 짧은 시간에 상당한(2-3만 개 초과) 숏 커넥션이 이 오류를 보일 수 있습니다. 이 경우 커널 파라미터를 조정하여 TIME_WAIT를 빠르게 재사용하도록 설정할 수 있으며, 자세한 내용은 커널 최적화를 참고하시기 바랍니다.

주의
로컬 포트 수 제한은 클라이언트에만 적용되며, 서버에는 해당 로컬 포트 제한이 없으며 리소스가 충분하면 서버는 연결 수를 무제한으로 유지할 수 있습니다.

기타 오류

만일 발생하는 오류가 "connection refuse(연결 거부)"나 "connection timeout(연결 시간 초과)"가 아닌 경우, 일반적으로 다음과 같은 이유로 발생합니다:

1. 클라이언트가 사용하는 통신 프로토콜이 서버와 일치하지 않음.
예를 들어, 서버가 HTTP 통신 프로토콜을 사용하고 있지만 클라이언트가 웹소켓 통신 프로토콜을 사용하여 접속하는 경우에는 연결할 수 없습니다. 클라이언트가 웹소켓 프로토콜을 사용하여 접속하고자 할 경우, 서버도 반드시 웹소켓 프로토콜을 사용해야 합니다. 서버가 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 연결(웹소켓 프로토콜)을 사용하고 있습니다. 서버도 웹소켓 프로토콜을 사용해야 합니다. 서버 리스닝 부분의 코드는 다음과 같이 웹소켓 프로토콜을 명시하여야 합니다.

만일 GatewayWorker를 사용한다면, 리스닝 부분의 코드는 다음과 같습니다.

// 웹소켓 프로토콜, 이렇게 하지 않으면 클라이언트는 ws://...를 통해 연결할 수 없습니다. xxxx는 포트를 변경할 필요가 없습니다.
$gateway = new Gateway('websocket://0.0.0.0:xxxx');

만일 Workerman을 사용한다면, 리스닝 부분의 코드는 다음과 같습니다.

// 웹소켓 프로토콜, 이렇게 하지 않으면 클라이언트는 ws://...를 통해 연결할 수 없습니다. xxxx는 포트를 변경할 필요가 없습니다.
$worker = new Worker('websocket://0.0.0.0:xxxx');