Overview
You’ve covered how to establish a peer-to-peer connection between a local peer and a remote peer. WebRTC supports real-time communication for other types of data, such as plain texts, images as well as streaming video. In this tutorial, you’ll learn how to transmit data via a peer connection.
Transmit Data Using RTCDataChannel
WebRTC allows you to transmit data between peers using RTCDataChannel that represents a network channel which can be used for bidirectional peer-to-peer transfers of data, such as plain texts and images.
You can create a data channel with the RTCPeerConnection’s createDataChannel() method like the example below:
const dataChannel = peerConnection.createDataChannel('sendDataChannel');
Next, you can transmit the data across the connection with the send() method, which receives string, a Blob, an ArrayBuffer, a TypedArray or a DataView object as a parameter.
const textarea = document.querySelector('textarea#dataChannelSend');
function sendData() {
const data = textarea.value;
dataChannel.send(data);
}
Transmit Data Between Multiple Peers
Now, let’s transmit data between multiple peers using the RTCDataChannel API and a peer connection.
Let’s assume a local peer want to transmit a plain text message to a remote peer in real time. You can send a plain text message from a local peer to a remote peer by implementing the code below:
'use strict';
let localConnection, remoteConnection;
let sendChannel, receiveChannel;
const dataChannelSend = document.querySelector('textarea#dataChannelSend');
const dataChannelReceive = document.querySelector('textarea#dataChannelReceive');
const connectButton = document.querySelector('button#connectButton');
const sendButton = document.querySelector('button#sendButton');
const disconnectButton = document.querySelector('button#disconnectButton');
connectButton.onclick = createConnection;
sendButton.onclick = sendData;
disconnectButton.onclick = closeDataChannels;
function createConnection() {
localConnection = new RTCPeerConnection();
remoteConnection = new RTCPeerConnection();
sendChannel = localConnection.createDataChannel('sendDataChannel');
remoteConnection.onicecandidate = e => {
onIceCandidate(remoteConnection, e);
};
remoteConnection.ondatachannel = receiveChannelCallback;
localConnection.createOffer().then(handleLocalSdp);
}
function handleLocalSdp(desc) {
localConnection.setLocalDescription(desc).then(onCatch);
remoteConnection.setRemoteDescription(desc).then(onCatch);
remoteConnection.createAnswer().then(
handleRemoteSdp,
onCatch
);
}
function handleRemoteSdp(desc) {
remoteConnection.setLocalDescription(desc).then(onCatch);
localConnection.setRemoteDescription(desc).then(onCatch);
}
function receiveChannelCallback(event) {
receiveChannel = event.channel;
receiveChannel.onmessage = onReceiveMessageCallback;
receiveChannel.onopen = onReceiveChannelStateChange;
receiveChannel.onclose = onReceiveChannelStateChange;
}
function onReceiveMessageCallback(event) {
dataChannelReceive.value = event.data;
}
function sendData() {
const data = dataChannelSend.value;
sendChannel.send(data);
console.log('Sent Data: ' + data);
}
Let’s break the above code snippet one by one:
createConnection()
: Creates local and remote peer connections and creates an SDP offer from the local peer. Also, it registersonReceiveMessageCallback
to the remote peer as a data channel.handleLocalSdp()
: This one is called bycreateConnection()
after creating the SDP offer. It receives a session description as a parameter and sets it as a local/remote description for each peer. Also, the remote peer creates an SDP answer.handleRemoteSdp()
: This is called bygotDescription1()
after creating an SDK answer. It receives a session description as a parameter and sets it as a local/remote description for each peer.onReceiveMessageCallback()
: This is called when the remote peer receives data via the data channel and handles an event from the data channel.onReceiveMessageCallback()
: This is called by theonReceiveMessageCallback()
method, which logs and displays the data from the data channel.sendData()
: Sends text messages from a text area by clicking thesend
button on the web browser.
You can utilize the RTCDataChannel API in various ways, such as implementing a chat feature, sharing an emoji feature.
Listen To State Changes Of a Data Channel
You can listen to the state changes of a data channel, such as opening or closing a data channel, and you can update the pages or something depending on the different states:
sendChannel.onopen = onSendChannelStateChange;
sendChannel.onclose = onSendChannelStateChange;
function onSendChannelStateChange() {
const readyState = sendChannel.readyState;
console.log('Send channel state is: ' + readyState);
if (readyState === 'open') {
// do something when a data channel is opened
} else {
// do something when a data channel is closed
}
}
The open
event is triggered in a data channel’s onopen event handler when the channel's message transmission is initiated or resumed. Conversely, the close
event is dispatched to the data channel’s onclose event handler once the channel is fully closed.
Additionally, you have the option to monitor these states by independently adding listeners, as demonstrated in the following example:
addEventListener(open, (event) => {});
onopen = (event) => {};
addEventListener(close, (event) => {});
onclose = (event) => {};
Close the Data Channel
Once you don’t need to connect the data channel anymore, you need to close the data channel. You can close the data channel with the close()
method like the example below:
function closeDataChannels() {
sendChannel.close();
receiveChannel.close();
localConnection.close();
remoteConnection.close();
localConnection = null;
remoteConnection = null;
}
In this lesson, you’ve learned the basic concepts of transmitting data between multiple peers with the RTCDataChannel API. Now, let’s create an HTML page that controls transmitting data.