WebRTCを使ってチャットを作ってみた

Blog Single

以前から興味があったWebRTCを触ってみようということで、チャットを作成してみました。ソース

それにあたってWebRTCの概要と、WebRTCの使い方をまとめてみたので記事にしました。

WebRTC 概要

Web Real-Time Communicationの略
Webブラウザ間でのpeer-to-peer接続をすばやく簡単に設定することができる。APIは2011年5月にリリースされ、現在も開発中です。

セキュリティ

暗号化はWebRTCの全ての構成要素で必須となっています。
実際にP2P通信を担っているWebRTCDataChannelの全てのデータは、Datagram Transport Layer Security (DTLS – The Wireshark Wiki)により、SSLベースの接続と同様の安全が保証されます。また、DTLSは標準化されていて、WebRTCをサポートする全てのブラウザに搭載されている

できること

  • ビデオやオーディオなどといったメディアのストリーム配信
  • DataChannelを介して文字列のやり取り

文字列のやり取りができるので実質無限に使い道があります。規格を決めることで相手の画面を操作することもできたりします。実際にChrome リモート デスクトップはWebRTCを使用しているようです。

WebRTC API

基本的なものは
RTCPeerConnection: ピアへの接続、接続の初期化、メディアストリームの添付など主要な動作を行う。
MediaStream: ビデオやオーディオへアクセス、使用の許可などを求める動作も行う。
RTCDataChannel: メディアストリームとは異なる追加データの送信を行う。テキストなどをやり取りできる。
の3つです。

どうして簡単にP2P接続ができるのか

本来P2P接続をするには、考慮することがたくさんありますが、WebRTCはそれらを裏に隠蔽して美味しいところだけ使える様にしています。
これを実現するために裏でICEサーバーが動いています。ICEは接続IPとポートのリストの取得と優先度決めを行います。
ICEにはVanillaとTrickleがあるようですが、理解のためにベーシックなVanillaICEを用いたP2P接続確立までの順序を簡単に図示してみました。

このような順序でP2P接続が行われます。

Datachannelを使ってチャットを実装してみる。

DataChannelではテキストを扱えるので試しにチャットを実装してみました。
すべて説明すると長いので端折りながらユーザーABでP2P接続するまでを説明してみます。
実装はこちらにあります。

まずはARTCPeerConnectionのインスタンス作成および、交換するためのリストを含むofferを作成します。

const peerConnection = new RTCPeerConnection({
  iceServers: [{urls: 'stun:stun.1.google.com:19302'}]
})
const offer = await peerConnection.createOffer()
peerConnection.setLocalDescription(offer)

このofferB側に送ります。
Bofferを登録して、answerを返します。

const peerConnection = new RTCPeerConnection({
  iceServers: [{urls: 'stun:stun.1.google.com:19302'}]
})
peerConnection.setRemoteDescription(offer)
const answer = peerConnection.createAnswer()
peerConnection.setLocalDescription(answer)

Aは、answerを登録します。
そうするとデータチャンネルが開通してP2Pでやり取りが可能となります。

peerConnection.setRemoteDescription(answer)
// A,Bともに以下の処理でP2Pでやり取りが可能になります。
sendDataChannel = peerConnection.createDataChannel('AtoBChannel');
sendDataChannel.send('hello')
// また、相手から送られてきたデータを見るには以下のようにイベントリスナーを登録します。
peerConnection.ondatachannel = function(event) {
  event.channel.onmessage = function(e) {
    console.log(e.data)
  }
}

以上です。

この記事を書き始めるときは、webpackを使ったでフロントエンド整備をネタに記事を書こうと思っていたんですが、書き終えるとWebRTCでチャットを実装していました🤔
P2P通信は以前から興味があったのでそこらへんを調べられたし、webpackも使えたのでWin-Win?でした。

参考

Posted by MachidaMamoru
typescriptとAngularが好き、最近Dapps開発にハマっています。

Other Posts: