クライアント接続失敗の理由

クライアント接続失敗時に一般的に二つのエラーが発生します。「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. BTパネルなどのパネルを使用している場合、対応するポートを開放する必要があります。
  4. サーバーが存在しないか、起動されていない可能性があります。
  5. クライアントがドメインを使用して接続する場合、ドメインが間違ったサーバーIPを指しているかもしれません。
  6. クライアントがアクセスしているIPがサーバーの内部IPであり、かつクライアントとサーバーが同じローカルネットワークにない場合があります。

cannot assign requested address(要求されたアドレスを割り当てることができません)

クライアントとして、接続するたびにローカルで一時ポートを使用する必要があります。サーバーごとに使用できる一時ポートの数は約2〜3万です。特定のサーバーに対する接続数がこの値を超えると、利用可能なポートを割り当てられなくなり、このエラーが発生します。

内核パラメータ/etc/sysctl.confnet.ipv4.ip_local_port_rangeを変更して、ローカルの一時ポート数を増やすことができます。たとえば、10000 65535に設定し、sysctl -pを実行して有効にします。

また、接続が切断された後、接続は依然としてTIME_WAIT状態になります。つまり、短時間で大量(2〜3万を超える)の短い接続を開始すると、「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

対処法:
上記の2つのエラーから分かるように、クライアントがws接続を使用している場合は、サーバーもwsプロトコルである必要があります。サーバーのリスニング部分のコードは、通信できるようにwsプロトコルを指定する必要があります。たとえば、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');