docs/rtc-datachannel-for-beginners.html
This tutorial is out-dated (written in 2013). Please check this tutorial instead: https://codelabs.developers.google.com/codelabs/webrtc-web/#0
| If you're newcomer, newbie or beginner; you're suggested to try RTCMultiConnection.js or DataChannel.js libraries. |
|
| | Copy below code and paste in Console Tab of Chrome Dev Tools (using Ctrl + Shift + i).
var iceServers = {
iceServers: [{
url: 'stun:stun.l.google.com:19302'
}]
};
var optionalRtpDataChannels = {
optional: [{
RtpDataChannels: true
}]
};
var offerer = new webkitRTCPeerConnection(iceServers, optionalRtpDataChannels),
answerer, answererDataChannel;
var offererDataChannel = offerer.createDataChannel('RTCDataChannel', {
reliable: false
});
setChannelEvents(offererDataChannel, 'offerer');
offerer.onicecandidate = function (event) {
if (!event || !event.candidate) return;
answerer && answerer.addIceCandidate(event.candidate);
};
var mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: false, // Hmm!!
OfferToReceiveVideo: false // Hmm!!
}
};
offerer.createOffer(function (sessionDescription) {
offerer.setLocalDescription(sessionDescription);
createAnswer(sessionDescription);
}, null, mediaConstraints);
function createAnswer(offerSDP) {
answerer = new webkitRTCPeerConnection(iceServers, optionalRtpDataChannels);
answererDataChannel = answerer.createDataChannel('RTCDataChannel', {
reliable: false
});
setChannelEvents(answererDataChannel, 'answerer');
answerer.onicecandidate = function (event) {
if (!event || !event.candidate) return;
offerer && offerer.addIceCandidate(event.candidate);
};
answerer.setRemoteDescription(offerSDP);
answerer.createAnswer(function (sessionDescription) {
answerer.setLocalDescription(sessionDescription);
offerer.setRemoteDescription(sessionDescription);
}, null, mediaConstraints);
}
function setChannelEvents(channel, channelNameForConsoleOutput) {
channel.onmessage = function (event) {
console.debug(channelNameForConsoleOutput, 'received a message:', event.data);
};
channel.onopen = function () {
channel.send('first text message over RTP data ports');
};
channel.onclose = function (e) {
console.error(e);
};
channel.onerror = function (e) {
console.error(e);
};
}
| | After executing above code in the console; try to send messages over RTP data ports like this:
offererDataChannel.send('message from offerer');
answererDataChannel.send('message from answerer');
| |
| | Copy below code and paste in Console Tab of Firefox Dev Tools (using Ctrl + Shift + i).
function setChannelEvents(channel, channelNameForConsoleOutput) {
channel.onmessage = function (event) {
console.debug(channelNameForConsoleOutput, 'received a message:', event.data);
};
channel.onopen = function () {
channel.send('first text message over SCTP data ports');
};
}
function useless() {}
var iceServers = {
iceServers: [{
url: 'stun:23.21.150.121'
}
]
};
var offerer = new mozRTCPeerConnection(iceServers),
answerer, answererDataChannel, offererDataChannel;
offererDataChannel = offerer.createDataChannel('channel', {});
offererDataChannel.binaryType = 'blob';
setChannelEvents(offererDataChannel, 'offerer');
navigator.mozGetUserMedia({
audio: true,
fake: true
}, function (stream) {
offerer.addStream(stream);
offerer.createOffer(function (sessionDescription) {
offerer.setLocalDescription(sessionDescription);
createAnswer(sessionDescription);
}, null, mediaConstraints);
}, useless);
var mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
}
};
function createAnswer(offerSDP) {
answerer = new mozRTCPeerConnection(iceServers);
answerer.ondatachannel = function (event) {
answererDataChannel = event.channel;
answererDataChannel.binaryType = 'blob';
setChannelEvents(answererDataChannel, 'answerer');
};
navigator.mozGetUserMedia({
audio: true,
fake: true
}, function (stream) {
answerer.addStream(stream);
answerer.setRemoteDescription(offerSDP);
answerer.createAnswer(function (sessionDescription) {
answerer.setLocalDescription(sessionDescription);
offerer.setRemoteDescription(sessionDescription);
}, null, mediaConstraints);
}, useless);
}
| | After executing above code in the console; try to send messages over SCTP data ports like this:
offererDataChannel.send('message from offerer');
answererDataChannel.send('message from answerer');
| |
There are following possible situations:
- A person wants to chat with his friend(s); share files directly; or share a part of the screen in realtime!
He is the offerer.- A person who receives an offer from a friend: so, he will join him. He is the answerer.
There are so many other possible situations. Let us go to the point.
| |
| |
The first situation: a person wants to make an offer request to his friend. He will create offer sdp and send that sdp to his friend.
First of all: we need to open a peer connection:
varpeerConnection= new **webkitRTCPeerConnection** (
{ " **iceServers**": [{ "url": " **stun** :stun.l.google.com:19302" }] },
{ **optional** : [{ **RtpDataChannels** : true}] }
);
RTCPeerConnection constructor takes two objects:
- ICE servers (STUN or TURN)
- Optional (like RtpDataChannels)
| |
Setting event handlers for peer connection object:
[peerConnection](#peerConnection). **onicecandidate** =[onicecandidate](#onicecandidate-func);[openDataChannel](#openDataChannel)();
In simple words: onicecandidate returns locally generated ICE candidates so you can pass them over other peer(s) via XHR or Socket.
| |
| |
var **channel** ;
function **openDataChannel** () {
if (! [peerConnection](#peerConnection)|| typeof[peerConnection](#peerConnection). **createDataChannel** == ' **undefined**') {
console.log('RTCDataChannel is not enabled. Use Chrome Canary '+
'and enable this flag via chrome://flags');
return;
}[channel](#channel)=[peerConnection](#peerConnection). **createDataChannel** (' **RTCDataChannel**',
{ **reliable** : false
}
);[channel](#channel). **onmessage** = function (event) {
console.log(event. **data** );
};[channel](#channel). **onopen** = function (event) {[channel](#channel). **send** ('RTCDataChannel opened.');
};[channel](#channel). **onclose** = function (event) {
console.log('RTCDataChannel closed.');
};[channel](#channel). **onerror** = function (event) {
console.error(event);
};[peerConnection](#peerConnection). **ondatachannel** = function () {
console.log('peerConnection.ondatachannel event fired.');
};
}
| |
| |
[channel](#channel). **send** ('JUST a text message');[channel](#channel). **send** (
JSON. **stringify** (
{
boolean: true,
integer: 1,
string: 'Wow!',
obj: { etc: 'etcetera' }
}
)
);
| |
| |
[peerConnection](#peerConnection). **createOffer** (function (sessionDescription) {[peerConnection](#peerConnection). **setLocalDescription** (sessionDescription);// POST-Offer-SDP-For-Other-Peer(sessionDescription. **sdp** , sessionDescription. **type** );}, null, { ' **mandatory**': { ' **OfferToReceiveAudio**': true, ' **OfferToReceiveVideo**': true } });
| |
| |
Assume that you sent offer sdp to your friend using XHR. Now, "process" that offer sdp and then create answer sdp and send it back to offerer:
[peerConnection](#peerConnection). **setRemoteDescription** (new **RTCSessionDescription** ([offerSDP](#offer-sdp)));[peerConnection](#peerConnection). **createAnswer** (function (sessionDescription) {[peerConnection](#peerConnection). **setLocalDescription** (sessionDescription);// POST-answer-SDP-back-to-Offerer(sessionDescription. **sdp** , sessionDescription. **type** );}, null, { ' **mandatory**': { ' **OfferToReceiveAudio**': true, ' **OfferToReceiveVideo**': true } });
| |
| |
[peerConnection](#peerConnection). **setRemoteDescription** (new **RTCSessionDescription** ([answerSDP](#answer-sdp)));
| | Offer/Answer exchange is done. What remaining are ICE candidates. | |
| |
function[onicecandidate](#onicecandidate)(event) {
if (! [peerConnection](#peerConnection)|| !event || !event.candidate) return;
var candidate = event. **candidate** ;// POST-ICE-to-other-Peer(candidate. **candidate** , candidate. **sdpMLineIndex** );}
| |
| |
[peerConnection](#peerConnection). **addIceCandidate** (new **RTCIceCandidate** ({ **sdpMLineIndex** : candidate. **sdpMLineIndex** , **candidate** : candidate. **candidate** }));
| |
| |
createDataChannel must be called before creating offer-sdp.| |
Are you interested in a "more" simple full-fledged guide? Read this document.
| |
Are you interested in a "simple" guide about RTCDataChannel? Read this document.
| | Are you interested to learn How to share files using RTCDataChannel APIs? |
Send MessageEnter your email too; if you want "direct" reply!