サーバー側では、websockets ライブラリの実装、言語、および API に依存するか、使用する独自の実装に依存します。
この説明は、WebSockets の RAW 実装についてのみ実際のものであり、WebSockets プロトコルを操作するためのライブラリの使用に基づいていません。jWebSockets (Java)、SignalR、socket.io などのライブラリには、WebSocket を操作するためのまったく別のプロセスがあります。
生のソケットでの生の実装について話している場合、プロセスは次のようになります。
- サーバー側の TCP ソケットを作成し、特定のポートにバインドしてリッスンし、受け入れ状態にします。受け入れは、ブロックまたは非ブロックにすることができます。私は.Netを使用し、サーバーへの接続があるたびにメソッドをトリガーするように非同期受け入れを行いました。1b. JS を介して呼び出されたクライアント: new WebSocket(...);
- 新しいソケットを受け入れた後、データの受信を開始する必要があります。TCP プロトコルはストリーム ベースですが、メッセージ ベースではありません。
- WebSockets プロトコルでは、通信する前に WebSockets の HTTP ハンドシェイクを行う必要があります。したがって、新しいソケットを受け入れた直後にデータの受信を開始し、最初に受信するのはハンドシェイク データ (数行のテキスト) です。
- 握手会を進めます。これは、ハンドシェイク データを読み取り、サーバー側で応答ハンドシェイク データを生成して WebSocket に送信することを意味します。4b. ハンドシェイク データがクライアント側 (ブラウザ) によって検証および検証される場合、コールバック "onopen" が返されます。それ以外の場合は、その後に "onerror" および "onclose" が返される可能性があります。
- ハンドシェイクが完了すると、メッセージを送受信できます。メッセージは、WebSockets プロトコルに基づいて (生ではなく) データフレーム化されます。WebSocket は MESSAGE ベースのプロトコルです。したがって、論理処理のためにデータを処理する前に、特定の量のメッセージ データを読み取る必要があります。
- サーバー側でデータを受信するために、独自の実装を使用する場合は、TCP ソケット ストリームからの読み取りを実装する必要があります。これを行うには、常に 2 バイトのみを読み取りたいと思うでしょう。いくつか (2 バイト) がある場合は、これはヘッダー データであり、プロトコル データ フレーミング仕様に基づいてデコードし、残りのデータを読み取り続けて、存在するかどうかを調べます。マスキングしてから、マスキング バイトと長さを読み取ります。それはすべてヘッダーにあります。ただし、ヘッダーの長さはわずかに異なる場合があります。そのため、最初に 2 バイトだけを読み取り、次にいくつかを読み取る必要があります。長さを取得したら、TCP ソケット ストリームから正確にこの長さのバイトを読み取る必要があります。すべてが読み取られ、実際のデータがマスク解除された後 (マスキングが有効になっている場合、私の経験では常に有効になっています)、その後、最初から他のデータを読み取るためにソケットを配置できます。
- メッセージが読み取られてマスク解除されると、生データが得られます。ほとんどの場合、それは "socket.send("...");" を使用してクライアントから送信された単なる文字列です。
- データを送信するには、生の文字列データを取得し、UTF8 エンコーディングを使用して文字列のバイトを取得し、それをデータ フレーミングでカバーする必要があるため、読み取りとは逆になります。違いは、マスキングを行う必要がないことだけです。そのため、サーバーからクライアントへのデータはマスクされません。
- バイナリを作成して送信した後、すべてが正しければ、送信したデータを含む「onmessage」がクライアント側で受信される場合があります。
クライアントは、データの一部または順序付けられていないデータを受け取ることはありません。送信した順序で常にパケットを受信し、常に送信したとおりに受信します。サーバーは、低レベルの TCP レイヤー プロセスに基づいて部分的にデータを受信する場合があります。しかし、常に注文を受けます。
このプロトコルは信頼性が高く、秩序立っています。
WebSockets プロトコルRFC 6455の最も一般的な仕様は、iOS が別の仕様を使用しており、相互互換性がない可能性があることを念頭に置いてください。つまり、別のハンドシェイク機能とデータ フレーミングを別のプロトコル実装専用に作成する必要があることを意味します。