クライアント接続失敗の理由
クライアント接続失敗時に一般的に二つのエラーが発生します。「connection refuse」と「connection timeout」です。
connection refuse(接続拒否)
通常、以下の理由が考えられます。
- クライアントが間違ったポートに接続している
- クライアントが誤ったドメインまたはIPに接続している
- クライアントがドメインを使用して接続する場合、ドメインが間違ったサーバーIPを指しているかもしれません。
- サーバーがCDNなどの高速プロキシを使用しており、実際の接続IPと予想されるIPが一致しないことがあります。
- サーバーが起動していないか、ポートがリッスンされていない可能性があります。
- ネットワークプロキシソフトウェアを使用している可能性があります。
- サーバーのリッスンIPとアクセスアドレスが同じアドレス範囲にない場合があります。たとえば、サーバーが127.0.0.1をリッスンしている場合、クライアントは127.0.0.1経由でのみ接続でき、ローカルネットワークIPまたはグローバルIPを介して接続できません。リッスンアドレスは0.0.0.0に設定することをお勧めします。これにより、ローカル、内部、外部のすべての接続が可能になります。
connection timeout(接続タイムアウト)
通常、以下の理由が考えられます。
- サーバーのファイアウォールが接続を阻止している可能性があります。一時的にファイアウォールを無効にしてみてください。
- クラウドサーバーの場合、セキュリティグループが接続確立をブロックしている可能性があります。対応するポートを管理コンソールから開放する必要があります。
- BTパネルなどのパネルを使用している場合、対応するポートを開放する必要があります。
- サーバーが存在しないか、起動されていない可能性があります。
- クライアントがドメインを使用して接続する場合、ドメインが間違ったサーバーIPを指しているかもしれません。
- クライアントがアクセスしているIPがサーバーの内部IPであり、かつクライアントとサーバーが同じローカルネットワークにない場合があります。
cannot assign requested address(要求されたアドレスを割り当てることができません)
クライアントとして、接続するたびにローカルで一時ポートを使用する必要があります。サーバーごとに使用できる一時ポートの数は約2〜3万です。特定のサーバーに対する接続数がこの値を超えると、利用可能なポートを割り当てられなくなり、このエラーが発生します。
内核パラメータ/etc/sysctl.conf
のnet.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');