7

Websocket 通信を理解する上でいくつか質問があります。AFAIU、クライアント側では、次のように機能します。

  1. クライアントから、「new WebSocket('ws://blahblah')」を使用して新しいソケット ハンドラーが作成されます。
  2. 次に、onOpen() メソッドを使用すると、WS サーバーに接続されていることがわかります
  3. onMessage() メソッドを使用すると、メッセージが WS サーバーから受信されたことがわかります
  4. OnClose() メソッドは、ソケット接続が閉じられていることを指示します

したがって、クライアントの観点からは明らかです。しかし、サーバーの観点からは、フローがどのように進行するか (上記のクライアントの場合)、websocket サーバー プロセスが正確に意味するものは何か、通信が TCP で発生することを正確に意味するものは何か、それをどのように確認するのか (質問が非常に基本的な)

誰か説明してくれませんか。事前に感謝します

4

2 に答える 2

8

サーバー側では、websockets ライブラリの実装、言語、および API に依存するか、使用する独自の実装に依存します。

この説明は、WebSockets の RAW 実装についてのみ実際のものであり、WebSockets プロトコルを操作するためのライブラリの使用に基づいていません。jWebSockets (Java)、SignalR、socket.io などのライブラリには、WebSocket を操作するためのまったく別のプロセスがあります。

生のソケットでの生の実装について話している場合、プロセスは次のようになります。

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

クライアントは、データの一部または順序付けられていないデータを受け取ることはありません。送信した順序で常にパケットを受信し、常に送信したとおりに受信します。サーバーは、低レベルの TCP レイヤー プロセスに基づいて部分的にデータを受信する場合があります。しかし、常に注文を受けます。

このプロトコルは信頼性が高く、秩序立っています。

WebSockets プロトコルRFC 6455の最も一般的な仕様は、iOS が別の仕様を使用しており、相互互換性がない可能性があることを念頭に置いてください。つまり、別のハンドシェイク機能とデータ フレーミングを別のプロトコル実装専用に作成する必要があることを意味します。

于 2012-05-18T14:52:58.100 に答える
0

ハンドシェイクが完了すると、メッセージを送受信できます。メッセージは、WebSocketプロトコルに基づいて(生ではなく)データフレーム化されます。また、WebSocketはMESSAGEベースのプロトコルです。したがって、論理処理のためにデータを処理する前に、特定の量のメッセージデータを必ず読み取る必要があります。

ここにこれに関するいくつかのより多くの情報があります:

そのため、サーバーは、クライアントに送信される複数のWebSocketフレームでメッセージをフラグメント化できます。

于 2012-05-28T02:25:09.247 に答える