QUICベースのデータチャネルは、現在のSCTPトランスポートの代替と見なされます。 Google WebRTCワーキンググループは既にそれらを実験しています:
それも試してみましょう。 これを行うために、テキスト送信用のWebRTCチャネルの例に似た1ページのアプリケーションを作成します -これは完全に機能する例(シグナリングサーバーなし)であり、さらにWebRTC DataChannelsを実装するアプローチを比較しやすくします。
始める前に、 DataChannelの基本を思い出しましょう。
DataChannelについて簡単に
WebRTCのデータチャネルにより、参加者は任意のデータを交換できます。 ファイルを転送するときに非常に役立つ信頼性の高いものと、ゲーム内の位置に関する情報として受け入れられる信頼性の低いものの両方があります。 APIは
RTCPeerConnection
拡張で
RTCPeerConnection
、次のようになります。
const dc = pc.createDataChannel("some label string"); // , – , – // send dc.send("some string"); // otherPc.addEventListener('datachannel', e => { const channel = e.channel; channel.onmessage = event => { console.log('received', event.data); }); });
公式のWebRTCサンプルページには、文字列とバイナリデータを送信する例があります 。
DataChannelはSCTPを使用します 。 オーディオおよびビデオストリームのRTPトランスポートと並行して動作します。 オーディオおよびビデオストリームで一般的に使用されるUDPとは異なり、SCTPは、単一の接続でチャネルを多重化する、信頼性のある、部分的に信頼性の高い(つまり、信頼性が高いが無秩序な)モードなど、他の多くの機能を提供します。
Googleは2012年にQUICを導入しました(プロトコルの歴史とそのニュアンスの詳細については、他の資料 -翻訳者のコメントをご覧ください )。 WebRTCと同様に、QUICプロトコルもIETFの管理下にあり、現在はHTTP / 3です。 QUICには、遅延の削減、輻輳制御に基づく帯域幅計算、直接遅延補正(FEC)、ローリングを高速化するための(カーネルではなく)ユーザー空間への実装など、多くの優れた革新があります。
QUICは、WebRTCのRTCPの代わりになる可能性があります-DataChannelのトランスポートのように。 現在の実験では、ICEトランスポートの別のバージョンを使用して、RTCPeerConnection API( およびSDP! )の使用を回避しようとしています。 それを少しのセキュリティと多くのNAT横断を加える仮想接続と考えてください。
以下のビデオでは、ChromeネットワーキングチームのIan Swettがこの概念を説明しています。 そして、この声明は数年前のものですが、このトピックに関する追加情報を提供しています。
QUICの最初のステップ
幸いなことに、 2015年の記事のほとんどのコードは関連性を保ち、新しいAPIに簡単に適応します。 それを理解しましょう。
ここからコードを複製するか、ここで試してください 。 実験がローカルで機能するためには、Chrome(バージョン73以降はカナリア)を特別なフラグで実行する必要があることに注意してください。
google-chrome-unstable --enable-blink-features=RTCQuicTransport,RTCIceTransportExtension
ICEトランスポートのセットアップ
RTCIceTransport仕様はORTCに基づいているため、セットアップは古いコードに似ています。
const ice1 = new RTCIceTransport(); ice1.onstatechange = function() { console.log('ICE transport 1 state change', ice1.state); }; const ice2 = new RTCIceTransport(); ice2.onstatechange = function() { console.log('ICE transport 2 state change', ice2.state); }; // ICE- ice1.onicecandidate = function(evt) { console.log('1 -> 2', evt.candidate); if (evt.candidate) { ice2.addRemoteCandidate(evt.candidate); } }; ice2.onicecandidate = function(evt) { console.log('2 -> 1', evt.candidate); if (evt.candidate) { ice1.addRemoteCandidate(evt.candidate); } }; // ICE- ice1.start(ice2.getLocalParameters(), 'controlling'); ice2.start(ice1.getLocalParameters(), 'controlled'); ice1.gather(iceOptions); ice2.gather(iceOptions);
ORTCとは異なり、このAPIにはRTCIceGathererがないことに注意してください。 ICEトランスポートのインストールに必要なものはすべて揃っているためです。
QUICトランスポートの構成
const quic1 = new RTCQuicTransport(ice1); quic1.onstatechange = function() { console.log('QUIC transport 1 state change', quic1.state); }; const quic2 = new RTCQuicTransport(ice2); quic2.onstatechange = function() { console.log('QUIC transport 2 state change', quic2.state); }; // QUIC quic2.addEventListener('quicstream', (e) => { console.log('QUIC transport 2 got a stream', e.stream); receiveStream = e.stream; });
ここでは、実験は証明書ベースの認証を使用する仕様から出発しています。 代わりに、 Google Developersの投稿にあるように、公開鍵が使用されます :
RTCQuicTransport接続は、API公開キーで構成されます。 現在、このAPIで元の検証を置き換える予定はありません。 QUICがChromiumでこれをサポートし始めると、自己署名証明書を検証するためのリモート証明書シグナリングに置き換えられます。これまでのところ、とても良い。
データを送受信するためのQUICStream
QUICStreamの使用は、WebRTC DataChannelより少し複雑です。 WHATWGワーキンググループによって作成されたStreams API( MDNの詳細を参照 )は受け入れられましたが、実装されていません 。
QUICトランスポートが「接続」状態になった後にのみ
sendStream
を作成します-異なる状態では、これはエラーにつながります。
quic1.onstatechange = function() { console.log('QUIC transport 1 state change', quic1.state); if (quic1.state === 'connected' && !sendStream) { sendStream = quic1.createStream('webrtchacks'); // createDataChannel. document.getElementById('sendButton').disabled = false; document.getElementById('dataChannelSend').disabled = false; } };
次に、ハンドラーを送信ボタンと入力フィールドにアタッチします。ボタンをクリックすると、入力フィールドのテキストがUint8Arrayでエンコードされ、ストリームに書き込まれます。
document.getElementById('sendButton').onclick = () => { const rawData = document.getElementById('dataChannelSend').value; document.getElementById('dataChannelSend').value = ''; // Uint8Array. , TextEncoder. const data = encoder.encode(rawData); sendStream.write({ data, }); };
最初のエントリは、リモートQUICトランスポートで
onquicstream
イベントをトリガーし
onquicstream
。
// QUIC quic2.addEventListener('quicstream', (e) => { console.log('QUIC transport 2 got a stream', e.stream); receiveStream = e.stream; receiveStream.waitForReadable(1) .then(ondata); });
...そして、データが読み取り可能になるまで待機します。
function ondata() { const buffer = new Uint8Array(receiveStream.readBufferedAmount); const res = receiveStream.readInto(buffer); const data = decoder.decode(buffer); document.getElementById('dataChannelReceive').value = data; receiveStream.waitForReadable(1) .then(ondata); }
receiveStream
からのすべてのデータが読み取られ、テキストにデコードされ、出力フィールドに配置されます。 そのため、読み取り可能なデータが表示されるたびに。
結論とコメント
この例が、Googleブログの類似例よりも理解しやすいことを願っています 。 この方法はP2P接続にはほとんど適しておらず、SCTPのDataChannelは既にそれらに適しています。 ただし、これは、もう一方の端にQUICサーバーを備えたWebソケットの興味深い代替手段になる可能性があります。 これが発生するまで、信頼性の低い不規則なチャネルで作業するための適切な方法を決定する必要があります。 私の意見では、前述の投稿からの提案は、決定よりもハッキングのように見えます。
開発者が外部からどのようなフィードバックを待っているかも不明です。 「ショートカットを再度作成するのではなく、すでに仕様を導入しています。これは数年間存続します」と言うのは明らかです。 さらに、コミュニティの一般的な意見はWHATWGストリームを使用する傾向があり、データを読み取るために独自のAPIをテストすることを求める奇妙な光の開発者を入れています。
また、ChromiumのSCTPに追加機能を追加したいと思います。 たとえば、 DataChannelに関するこのクエリ(ちなみに最高評価のクエリ)は、3年間ほとんど変更されていません。 SCTPタスクがまだあるのに、なぜQUICに焦点が当てられているのかは完全には明らかではありません。 ただし、これにより、QUICのテストと結果に関するフィードバックが停止されることはありません。
Voximplantによるコメント
フロントエンドのリードirbisadmへの一言 :
長い間、SDKはWebソケットの通知に使用されてきました。 これは優れた、実績のある標準ですが、いくつかの問題があります。 1つはTCPです。 また、TCPはモバイルネットワークではそれほど高速でなく、ネットワーク間のローミングもサポートしていません。 第二に、それは多くの場合、テキスト形式です(バイナリモードもありますが、めったに表示されません)。
最近、DataChannelのシグナリングプロトコルのクローズドベータテストを開始しました。 このプロトコルにも欠点がないわけではありませんが、貧弱なネットワークで動作し、ローミング時に一目で征服します。 ネットワークを変更しましたか? 接続を再作成する必要はありません。 ほとんどの場合、ICE Restart
は、トラフィックの新しい方法を見つけるのに役立ちます。 しかし、私が言ったように、プロトコルにはまだ欠点があります。すべてのブラウザが、配信の保証やパケット順序のサポートなど、すべてのプロトコル拡張をサポートしているわけではありません。 また、このプロトコルは、テキストモードですぐに使用できるgzipをサポートしていません。 しかし、これらの問題はすべてアプリケーション側で解決できます。