WebRTC データ チャネルを使用してブラウザ間でデータを送信する

通信、ゲーム、ファイル転送のために 2 つのブラウザ間でデータを送信するには、かなり複雑なプロセスが必要になることがあります。データを中継するサーバーを設定して料金を支払い、複数のデータセンターにスケーリングする必要がある場合があります。このシナリオでは、レイテンシが高くなる可能性があり、データのプライバシーを保護することが困難です。

これらの問題は、WebRTC の RTCDataChannel API を使用してピア間でデータを直接転送することで軽減できます。この記事では、データチャンネルの設定方法と使用方法の基本と、現在のウェブでの一般的なユースケースについて説明します。

別のデータチャネルが必要な理由

WebSocketAJAXServer Sent Events があります。別のコミュニケーション チャネルが必要なのはなぜですか?WebSocket は双方向ですが、これらのテクノロジーはすべてサーバーとの通信用に設計されています。

RTCDataChannel は異なるアプローチを取ります。

  • これは、ピアツーピア接続を可能にする RTCPeerConnection API と連携して動作します。これにより、レイテンシを短縮できます。中間サーバーがなく、ホップ数が少ないためです。
  • RTCDataChannelStream Control Transmission Protocol(SCTP)を使用し、順序外配信と再送信構成という構成可能な配信セマンティクスを可能にします。

RTCDataChannel は、Google Chrome、Opera、Firefox のパソコン版と Android 版で SCTP サポートとともに利用できるようになりました。

注意: シグナリング、STUN、TURN

WebRTC によってピアツーピア通信が可能になっても、メディアとネットワークのメタデータを交換してピア接続をブートストラップするためのシグナリングにはサーバーが必要です。

WebRTC は、次の方法で NAT とファイアウォールに対応します。

  • ピア間で可能な限り最適なネットワーク パスを確立するための ICE フレームワーク
  • 各ピアの一般公開されている IP とポートを特定するための STUN サーバー
  • 直接接続が失敗し、データのリレーが必要な場合は TURN サーバー

シグナリングとネットワーキングのためのサーバーで WebRTC がどのように動作するかについて詳しくは、WebRTC inthe real world: STUN, TURN, and signaling をご覧ください。

機能

RTCDataChannel API は、柔軟なデータ型のセットをサポートしています。この API は WebSocket を正確に模倣するように設計されており、RTCDataChannel文字列だけでなく、JavaScript の一部のバイナリ型(BlobArrayBufferArrayBufferView など)もサポートしています。これらのタイプは、ファイル転送やマルチプレーヤー型ゲームで役立ちます。

RTCDataChannel は、信頼性が低く順序付けされていないモード(User Datagram Protocol(UDP)に類似)、信頼性が高く順序付けされているモード(Transmission Control Protocol(TCP)に類似)、部分的に信頼性の高いモードで動作できます。

  • 信頼性の高い順序モードでは、メッセージの送信と配信順序が保証されます。このモードではオーバーヘッドが増えるため、速度が低下する可能性があります。
  • 信頼性が低く順序が保証されないモードでは、すべてのメッセージが相手側に届くことや、届く順序は保証されません。これによりオーバーヘッドが削減され、このモードが大幅に高速化されます。
  • 部分信頼モードでは、再送信タイムアウトや再送信の最大回数などの特定の条件でメッセージの送信が保証されます。メッセージの順序も構成可能です。

パケットロスがない場合、最初の 2 つのモードのパフォーマンスはほぼ同じです。ただし、信頼性の高い順序モードでは、パケットが失われると、他のパケットがその背後でブロックされ、再送信されて到着するまでに失われたパケットが古くなる可能性があります。もちろん、同じアプリ内で複数のデータチャンネルを使用することも可能です。各チャンネルには、信頼性の高いセマンティクスまたは信頼性の低いセマンティクスが設定されています。

Ilya Grigorik 氏の著書『High Performance Browser Networking』から、役立つ表を引用します。

TCPUDPSCTP
信頼性信頼性信頼性が低い構成可能
配信注文済み順序なし構成可能
感染バイト指向メッセージ指向メッセージ指向
フロー制御×
輻輳制御×

次に、信頼性の高い順序付きモードまたは信頼性の低い順序なしモードを使用するように RTCDataChannel を構成する方法について説明します。

データチャンネルの構成

RTCDataChannel の簡単なデモがオンラインでいくつか公開されています。

これらの例では、ブラウザが自身へのピア接続を行い、データチャンネルを作成して、ピア接続を介してメッセージを送信します。次に、データチャネルを作成し、ピア接続に沿ってメッセージを送信します。最後に、メッセージがページの反対側のボックスに表示されます。

このコードは短く、すぐに始められます。

const peerConnection = new RTCPeerConnection();

// Establish your peer connection using your signaling channel here
const dataChannel =
  peerConnection.createDataChannel("myLabel", dataChannelOptions);

dataChannel.onerror = (error) => {
  console.log("Data Channel Error:", error);
};

dataChannel.onmessage = (event) => {
  console.log("Got Data Channel Message:", event.data);
};

dataChannel.onopen = () => {
  dataChannel.send("Hello World!");
};

dataChannel.onclose = () => {
  console.log("The Data Channel is Closed");
};

dataChannel オブジェクトは、すでに確立されているピア接続から作成されます。シグナリングの前後に作成できます。次に、このチャンネルを他のチャンネルと区別するためのラベルと、一連のオプションの構成設定を渡します。

const dataChannelOptions = {
  ordered: false, // do not guarantee order
  maxPacketLifeTime: 3000, // in milliseconds
};

maxRetransmits オプション(失敗するまでの試行回数)を追加することもできますが、maxRetransmits と maxPacketLifeTime のいずれか一方のみを指定できます。両方を指定することはできません。UDP セマンティクスの場合、maxRetransmits0 に、orderedfalse に設定します。詳細については、IETF RFC の Stream Control Transmission ProtocolStream Control Transmission Protocol Partial Reliability Extension をご覧ください。

  • ordered: データチャンネルが順序を保証するかどうか
  • maxPacketLifeTime: 失敗したメッセージの再送信を試みる最大時間
  • maxRetransmits: 失敗したメッセージの再送信を試みる最大回数
  • protocol: サブプロトコルを使用して、アプリにメタ情報を提供できるようにします
  • negotiated: true に設定すると、他のピアでのデータチャネルの自動設定が削除され、同じ ID のデータチャネルを他のピアで作成する独自の方法が提供されます。
  • id: チャンネルに独自の ID を指定できます(negotiatedtrue に設定されている場合にのみ使用できます)。

ほとんどのユーザーが使用する必要があるのは、最初の 3 つのオプション(orderedmaxPacketLifeTimemaxRetransmits)のみです。SCTP(現在 WebRTC をサポートするすべてのブラウザで使用されています)では、reliable と ordered はデフォルトで true になっています。アプリレイヤから完全に制御したい場合は、信頼性が低く順序付けされていないものを使用するのが理にかなっていますが、ほとんどの場合、部分的な信頼性で十分です。

WebSocket と同様に、RTCDataChannel は接続の確立、切断、エラーが発生したときや、他のピアからメッセージを受信したときにイベントを発生させます。

それは安全?

すべての WebRTC コンポーネントで暗号化が必須です。RTCDataChannel では、すべてのデータが Datagram Transport Layer Security(DTLS)で保護されます。DTLS は SSL の派生であるため、データは標準の SSL ベースの接続を使用する場合と同じくらい安全です。DTLS は標準化されており、WebRTC をサポートするすべてのブラウザに組み込まれています。詳細については、Wireshark wiki をご覧ください。

データの考え方を変える

JavaScript で大量のデータを処理するのは難しい場合があります。Sharefest の開発者が指摘したように、これには新しい方法でデータを考える必要がありました。使用可能なメモリ容量よりも大きなファイルを転送する場合は、この情報を保存する新しい方法を検討する必要があります。ここで、FileSystem API などのテクノロジーが役立ちます。

ファイル共有アプリを構築する

RTCDataChannel を使用すると、ブラウザでファイルを共有できるウェブアプリを作成できるようになりました。RTCDataChannel をベースに構築すると、転送されたファイルデータが暗号化され、アプリ プロバイダのサーバーにアクセスしなくなります。この機能と、複数のクライアントに接続して共有を高速化できる可能性を組み合わせることで、WebRTC ファイル共有はウェブの有力な候補となります。

移行を成功させるには、次の手順が必要です。

  1. File API を使用して JavaScript でファイルを読み取ります。
  2. RTCPeerConnection を使用してクライアント間のピア接続を行います。
  3. RTCDataChannel を使用してクライアント間にデータチャネルを作成します。

RTCDataChannel でファイルを送信しようとする場合は、次の点に注意してください。

  • ファイルサイズ: ファイルサイズが適度に小さく、1 つの Blob として保存して読み込むことができる場合は、File API を使用してメモリに読み込み、信頼性の高いチャネルを介してそのまま送信できます(ただし、ブラウザには最大転送サイズに関する制限があることに注意してください)。ファイルサイズが大きくなるにつれて、処理が難しくなります。チャンク メカニズムが必要な場合、ファイル チャンクが読み込まれて別のピアに送信されます。このとき、ピアがチャンクを認識できるように chunkID メタデータが添付されます。この場合、まずチャンクをオフライン ストレージに保存し(FileSystem API を使用するなど)、ファイル全体が揃ったときにのみユーザーのディスクに保存する必要があります。
  • チャンクサイズ: アプリのデータの最小単位です。現在送信サイズに制限があるため、チャンク化が必要です(ただし、これはデータチャネルの将来のバージョンで修正される予定です)。現在推奨される最大チャンクサイズは 64 KiB です。

ファイルが完全に転送されたら、アンカータグを使用してダウンロードできます。

function saveFile(blob) {
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'File Name';
  link.click();
};

PubShareGitHub のファイル共有アプリは、この手法を使用しています。どちらもオープンソースであり、RTCDataChannel に基づくファイル共有アプリの基盤として適しています。

ではどうすればよいでしょうか。

RTCDataChannel は、ファイル共有、マルチプレイヤー ゲーム、コンテンツ配信用のアプリを構築する新しい方法への扉を開きます。

  • 前述のピアツーピア ファイル共有
  • Mozilla の BananaBread で見られるように、WebGL などの他のテクノロジーと組み合わせたマルチプレーヤー ゲーム
  • ピアツーピア データ通信を通じてウェブ アセットを配信するフレームワークである PeerCDN によって再発明されたコンテンツ配信

アプリの構築方法を変える

RTCDataChannel を介した高パフォーマンス、低レイテンシの接続を使用して、より魅力的なアプリを提供できるようになりました。PeerJSPubNub WebRTC SDK などのフレームワークにより、RTCDataChannel の実装が容易になり、API はプラットフォーム全体で幅広くサポートされるようになりました。

RTCDataChannel の登場により、ブラウザでのデータ転送の考え方が変わる可能性があります。

関連リソース