Did you know? All Video & Audio API plans include a $100 free usage credit each month so you can build and test risk-free. View Plans ->

WebRTC For The Brave

Real-Time Data Transmitting With WebRTC

In this lesson, you'll how to transmit messages via a data channel and peer connection.

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:

jsx
            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.

jsx
            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:

jsx
            '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 registers onReceiveMessageCallback to the remote peer as a data channel.
  • handleLocalSdp(): This one is called by createConnection() 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 by gotDescription1() 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 the onReceiveMessageCallback() method, which logs and displays the data from the data channel.
  • sendData(): Sends text messages from a text area by clicking the send 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:

jsx
            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:

jsx
            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:

jsx
            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.