48

私はより定期的に WebSocket 接続を使用しているので、内部でどのように動作するかに興味がありました。そこで、エンドレスの仕様書をしばらく掘り下げましたが、これまでのところ、伝送ストリーム自体をチャンク化することについては何も見つかりませんでした。

WebSocket プロトコルはこれをデータ フレームと呼びます (純粋なデータ ストリームを表すため、非制御フレームとも呼ばれます)。私が仕様を理解している限り、定義された最大長と定義された MTU (最大転送単位) 値はありません。つまり、単一の WebSocket データフレームには、仕様 (!) によって無限の量のデータが含まれる可能性があります。 (ここで間違っている場合は訂正してください。私はまだ学生です)。

それを読んだ後、私はすぐに小さなNode WebSocket サーバーをセットアップしました。私はAjaxの歴史が強いので(ストリーミングとコメットについても)、当初の私の期待は、「転送中にデータを読み取るための何らかのインタラクティブ モードが必要だ」というものでした。しかし、私は間違っていますよね?

4kbのデータから始めました。

サーバ

testSocket.emit( 'data', new Array( 4096 ).join( 'X' ) );

予想どおり、これは 1 つのデータチャンクとしてクライアントに到着します

クライアント

wsInstance.onmessage = function( data ) {
    console.log( data.length ); // 4095
};

そのため、ペイロードを増やしましたが、実際には、ある時点でクライアント側のonmessageハンドラーが繰り返し起動し、送信を効果的にチャンクすることを期待していました。しかし、私のショックなことに、それは決して起こりませんでした(node-server 、 firefoxchrome、およびsafariクライアント側でテスト済み)。私の最大のペイロードは80 MBでした

testSocket.emit( 'data', new Array( 1024*1024*80 ).join( 'X' ) );

そして、それはまだクライアント上の 1 つの大きなデータ チャンクに到着しました。もちろん、接続が良好な場合でも、これには時間がかかります。ここでの質問は

  • XHR readyState3 モードと同様に、これらのストリームをチャンクする可能性はありますか?
  • 単一の ws データ フレームにサイズ制限はありますか?
  • Websocket はそのような大きなペイロードを転送するはずがないのですか? (これは、定義された最大サイズがない理由をもう一度不思議に思うでしょう)

私はまだWebSocketについて間違った視点から見ているかもしれません.おそらく大量のデータを送信する必要はなく、送信する前に自分でデータを論理的にチャンク/分割する必要がありますか?

4

2 に答える 2

88

まず、ブラウザ内でWebSocketプロトコルと WebSocket APIを区別する必要があります。

WebSocket プロトコルには 2^63 オクテットのフレーム サイズ制限がありますが、WebSocket メッセージは無制限の数のフレームで構成できます。

ブラウザー内の WebSocket API は、フレーム ベースまたはストリーミング API を公開せず、メッセージ ベースの API のみを公開します。受信メッセージのペイロードは、JavaScript に提供される前に、(ブラウザの WebSocket 実装内で) 常に完全にバッファリングされます。

他の WebSocket 実装の API は、WebSocket プロトコルを介して転送されるペイロードへのフレーム ベースまたはストリーミング ベースのアクセスを提供する場合があります。たとえば、AutobahnPythonはそうします。https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/websocket/streamingの例で詳細を読むことができます。

開示: 私は Autobahn のオリジナルの作者であり、Tavendo で働いています。

その他の考慮事項:

ブラウザーの JS WebSocket API にフレーム/ストリーミング API がない限り、完全な WS メッセージのみを送受信できます。

単一の (プレーンな) WebSocket 接続では、複数のメッセージのペイロードをインターリーブできません。つまり、大きなメッセージを使用する場合、それらは順番に配信され、大きなメッセージがまだその場で送信されている間に小さなメッセージを送信することはできません。

今後の WebSocket 拡張機能があります (拡張機能は、プロトコルを拡張するための組み込みメカニズムです): WebSocket 多重化。これにより、複数の利点を持つ単一の基礎となる TCP 接続を介して複数の (論理) WebSocket 接続を持つことができます。

また、現在、単一の JS / HTML ページから単一のターゲット サーバーへの複数の WS 接続を (さまざまな基礎となる TCP を介して) 開くことができます

また、アプリケーション層で自分自身を「チャンク」することもできます。小さな WS メッセージで自分のものを送信し、自分で再構築します。

理想的な世界では、ブラウザーにメッセージ/フレーム/ストリーミング API と WebSocket の多重化があると思います。それはすべての力と便利さを与えるでしょう。

于 2012-10-22T12:13:32.400 に答える
10

RFC 6455 セクション 1.1 :

これが WebSocket プロトコルが提供するものです: [...] Web ページからリモート サーバーへの双方向通信のための HTTP ポーリングの代替手段。

前述のとおり、WebSocket は Web ページとサーバー間の通信用です。Webページと Webブラウザの違いに注意してください。使用されている例は、多くの小さなメッセージを交換するブラウザ ゲームやチャット アプリケーションです。

1 つのメッセージで多くの MB を送信したい場合は、意図したとおりに WebSocket を使用していないと思います。ファイルを転送したい場合は、Plain Old Http Request を使用して転送しContent-Disposition、ブラウザがファイルをダウンロードできるように応答します。

したがって、なぜこのような大量のデータを送信したいのかを説明すると、WebSocket を使用するよりも洗練されたソリューションを考え出すのに役立つ人がいるかもしれません。

さらに、クライアントまたはサーバーは大きすぎるメッセージを拒否する場合があります (ただし、どのように拒否するかは明示されていません)。

RFC 6455 セクション 10.4 :

複数のフレームからの再構成後のフレーム サイズまたは合計メッセージ サイズに関して、実装および/またはプラットフォーム固有の制限がある実装は、それらの制限を超えないように保護する必要があります。(たとえば、悪意のあるエンドポイントは、単一の大きなフレーム (サイズ 2**60 など) を送信するか、小さなフレームの長いストリームを送信することによって、ピアのメモリを使い果たしたり、サービス拒否攻撃を仕掛けたりすることができます。断片化されたメッセージの一部です。) このような実装では、複数のフレームからの再構成後のフレーム サイズとメッセージの合計サイズに制限を課す必要があります (SHOULD)。

于 2012-10-24T12:44:52.993 に答える