通信、ゲーム、ファイル転送のために 2 つのブラウザ間でデータを送信するのは、かなり複雑なプロセスになる可能性があります。データのリレーを行うサーバーを設定して料金を支払う必要があり、場合によっては複数のデータセンターにスケーリングする必要があります。このシナリオでは、レイテンシが高くなる可能性があり、データを非公開に保つのが難しくなります。
これらの問題は、WebRTC の RTCDataChannel
API を使用してピア間でデータを直接転送することで軽減できます。この記事では、データ チャネルの設定方法と使用方法の基本と、ウェブでの一般的なユースケースについて説明します。
別のデータ チャネルを使用する理由
WebSocket、AJAX、サーバー送信イベントがあります。なぜ別のコミュニケーション チャネルが必要なのか?WebSocket は双方向ですが、これらのテクノロジーはすべて、サーバーとの通信用に設計されています。
RTCDataChannel
は別のアプローチをとっています。
- これは、ピアツーピア接続を可能にする
RTCPeerConnection
API と連携します。これにより、中間サーバーがなく「ホップ」が少ないため、レイテンシを低く抑えることができます。 RTCDataChannel
は ストリーム制御伝送プロトコル(SCTP)を使用します。これにより、配信セマンティクスの構成(順序付けされていない配信と再送信の構成)が可能になります。
RTCDataChannel
は、パソコンと Android の Google Chrome、Opera、Firefox で SCTP をサポートして利用できるようになりました。
留意点: シグナリング、STUN、TURN
WebRTC ではピアツーピア通信が可能になりますが、ピア接続をブートストラップするためにメディアとネットワークのメタデータを交換するシグナリングを行うサーバーが必要です。
WebRTC は、次の方法で NAT とファイアウォールに対応します。
- ICE フレームワーク: ピア間で最適なネットワーク パスを確立します。
- STUN サーバー: 各ピアの一般公開されている IP とポートを確認します。
- TURN サーバー: 直接接続に失敗し、データリレーが必要な場合。
WebRTC がサーバーとどのように連携してシグナリングとネットワーキングを行うかについて詳しくは、実際の WebRTC: STUN、TURN、シグナリングをご覧ください。
機能
RTCDataChannel
API は、柔軟なデータ型のセットをサポートしています。この API は WebSocket を正確に模倣するように設計されており、RTCDataChannel
は文字列と、JavaScript の一部のバイナリ型(Blob、ArrayBuffer、ArrayBufferView など)をサポートしています。これらのタイプは、ファイル転送やマルチプレーヤー ゲームで役立ちます。
RTCDataChannel
は、信頼性が低く順序付けされていないモード(User Datagram Protocol または UDP に類似)、信頼性が高く順序付けられたモード(Transmission Control Protocol または TCP に類似)、部分的に信頼できるモードで動作できます。
- 信頼性と順序付けモードでは、メッセージの送信と配信順序が保証されます。これによりオーバーヘッドが増加し、このモードの速度が低下する可能性があります。
- 信頼できない順序なしモードでは、すべてのメッセージが相手側に届くことや、届く順序が保証されません。これによりオーバーヘッドが解消され、このモードの動作が大幅に高速化されます。
- 部分信頼モードでは、再送信タイムアウトや再送信の最大回数など、特定の条件下でメッセージの送信が保証されます。メッセージの順序も構成できます。
最初の 2 つのモードのパフォーマンスは、パケットロスがない場合とほぼ同じです。ただし、信頼性と順序付けのモードでは、パケットが失われると、他のパケットがブロックされ、失われたパケットが再送信されて届くまでに古くなる可能性があります。もちろん、信頼性の高いセマンティクスか信頼性の低いセマンティクスをそれぞれ備えた複数のデータ チャネルを、同じアプリ内で使用することも可能です。
Ilya Grigorik 著の High Performance Browser Networking に、役立つ表が掲載されています。
TCP | UDP | SCTP | |
信頼性 | 信頼性 | 信頼性が低い | 構成可能 |
配信 | 注文済み | 順序なし | 構成可能 |
感染 | バイト指向 | メッセージ指向 | メッセージ指向 |
フロー制御 | はい | いいえ | はい |
輻輳制御 | はい | いいえ | はい |
次に、信頼性の高い順序付きモードまたは信頼性のない順序なしモードを使用するように 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 セマンティクスについては、maxRetransmits
を 0
に、ordered
を false
に設定します。詳細については、IETF RFC の Stream Control Transmission Protocol と Stream Control Transmission Protocol Partial Reliability Extension をご覧ください。
ordered
: データ チャネルで順序を保証するかどうかmaxPacketLifeTime
: 失敗したメッセージの再送信を試行する最大時間maxRetransmits
: 失敗したメッセージの再送信の最大回数protocol
: サブプロトコルを使用できるようにします。これにより、アプリのメタ情報が提供されます。negotiated
: true に設定すると、もう一方のピアでのデータチャネルの自動設定が解除され、もう一方のピアで同じ ID のデータチャネルを独自の方法で作成できるようになります。id
:negotiated
をtrue
に設定した場合にのみ使用できる、チャネルの独自の ID を指定できます。
ほとんどのユーザーが使用する必要があるのは、最初の 3 つのオプション(ordered
、maxPacketLifeTime
、maxRetransmits
)のみです。SCTP(現在、WebRTC をサポートするすべてのブラウザで使用)では、信頼性と順序付けはデフォルトで true です。アプリレイヤから完全に制御したい場合は、信頼性が低く順序付けされていないものを使用するのが合理的ですが、ほとんどの場合、部分的な信頼性が有用です。
WebSocket と同様に、RTCDataChannel
は接続が確立されたとき、閉じられたとき、またはエラーが発生したときと、他のピアからメッセージを受信したときにイベントを起動します。
それは安全?
暗号化は、すべての WebRTC コンポーネントに必須です。RTCDataChannel
では、すべてのデータが Datagram Transport Layer Security(DTLS)で保護されます。DTLS は SSL の派生物です。つまり、標準的な SSL ベースの接続を使用する場合と同様に、データの安全性が確保されます。DTLS は標準化されており、WebRTC をサポートするすべてのブラウザに組み込まれています。詳細については、Wireshark のウィキをご覧ください。
データに対する考え方を変える
JavaScript では、大量のデータの処理が問題になることがあります。Sharefest のデベロッパーが指摘したように、そのためにはデータについて新しい考え方をする必要がありました。使用可能なメモリ量よりも大きいファイルを転送する場合は、この情報を保存するための新しい方法を検討する必要があります。ここで役立つのが FileSystem API などのテクノロジーです。
ファイル共有アプリを作成する
RTCDataChannel
を使用すると、ブラウザでファイルを共有できるウェブアプリを作成できるようになりました。RTCDataChannel
上に構築すると、転送されたファイルデータが暗号化され、アプリ プロバイダのサーバーには影響を与えません。この機能と、複数のクライアントに接続してより迅速に共有できる可能性を組み合わせることで、WebRTC ファイル共有はウェブでの使用に適した候補となります。
送金が正常に行われるようにするには、いくつかの手順が必要です。
- File API を使用して JavaScript でファイルを読み取る
RTCPeerConnection
を使用してクライアント間でピア接続を作成します。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();
};
PubShare や GitHub のファイル共有アプリでは、この手法が使用されています。どちらもオープンソースであり、RTCDataChannel
ベースのファイル共有アプリの優れた基盤となります。
ではどうすればよいでしょうか。
RTCDataChannel
により、ファイル共有、マルチプレイヤー ゲーム、コンテンツ配信用のアプリを新しい方法で構築できるようになります。
- 前述のピアツーピア ファイル共有
- Mozilla の BananaBread で見つかるような、WebGL などの他のテクノロジーと組み合わせたマルチプレーヤー型ゲーム
- コンテンツ配信の再発明: ピアツーピアのデータ通信を通じてウェブアセットを配信するフレームワークである PeerCDN
アプリの作成方法を変更する
RTCDataChannel
を介した高パフォーマンスで低レイテンシの接続を使用することで、より魅力的なアプリを提供できるようになりました。PeerJS や PubNub WebRTC SDK などのフレームワークを使用すると、RTCDataChannel
を簡単に実装できます。また、この API はプラットフォーム間で幅広くサポートされています。
RTCDataChannel
の登場により、ブラウザでのデータ転送に対する考え方が変わる可能性があります。