Теперь давайте создадим простой пример. Во-первых, запустите сервер сигнализации, который мы создали в руководстве «Сервер сигнализации», через «сервер узла».
На странице будет три текстовых ввода: один для логина, один для имени пользователя и один для сообщения, которое мы хотим отправить другому партнеру. Создайте файл index.html и добавьте следующий код —
<html lang = "en"> <head> <meta charset = "utf-8" /> </head> <body> <div> <input type = "text" id = "loginInput" /> <button id = "loginBtn">Login</button> </div> <div> <input type = "text" id = "otherUsernameInput" /> <button id = "connectToOtherUsernameBtn">Establish connection</button> </div> <div> <input type = "text" id = "msgInput" /> <button id = "sendMsgBtn">Send text message</button> </div> <script src = "client.js"></script> </body> </html>
Мы также добавили три кнопки для входа в систему, установления соединения и отправки сообщения. Теперь создайте файл client.js и добавьте следующий код —
var connection = new WebSocket('ws://localhost:9090'); var name = ""; var loginInput = document.querySelector('#loginInput'); var loginBtn = document.querySelector('#loginBtn'); var otherUsernameInput = document.querySelector('#otherUsernameInput'); var connectToOtherUsernameBtn = document.querySelector('#connectToOtherUsernameBtn'); var msgInput = document.querySelector('#msgInput'); var sendMsgBtn = document.querySelector('#sendMsgBtn'); var connectedUser, myConnection, dataChannel; //when a user clicks the login button loginBtn.addEventListener("click", function(event) { name = loginInput.value; if(name.length > 0) { send({ type: "login", name: name }); } }); //handle messages from the server connection.onmessage = function (message) { console.log("Got message", message.data); var data = JSON.parse(message.data); switch(data.type) { case "login": onLogin(data.success); break; case "offer": onOffer(data.offer, data.name); break; case "answer": onAnswer(data.answer); break; case "candidate": onCandidate(data.candidate); break; default: break; } }; //when a user logs in function onLogin(success) { if (success === false) { alert("oops...try a different username"); } else { //creating our RTCPeerConnection object var configuration = { "iceServers": [{ "url": "stun:stun.1.google.com:19302" }] }; myConnection = new webkitRTCPeerConnection(configuration, { optional: [{RtpDataChannels: true}] }); console.log("RTCPeerConnection object was created"); console.log(myConnection); //setup ice handling //when the browser finds an ice candidate we send it to another peer myConnection.onicecandidate = function (event) { if (event.candidate) { send({ type: "candidate", candidate: event.candidate }); } }; openDataChannel(); } }; connection.onopen = function () { console.log("Connected"); }; connection.onerror = function (err) { console.log("Got error", err); }; // Alias for sending messages in JSON format function send(message) { if (connectedUser) { message.name = connectedUser; } connection.send(JSON.stringify(message)); };
Вы можете видеть, что мы устанавливаем сокет-соединение с нашим сигнальным сервером. Когда пользователь нажимает кнопку входа в систему, приложение отправляет свое имя пользователя на сервер. Если вход выполнен успешно, приложение создает объект RTCPeerConnection и настраивает обработчик onicecandidate, который отправляет все найденные icecandidates другому партнеру. Он также запускает функцию openDataChannel (), которая создает dataChannel. Обратите внимание, что при создании объекта RTCPeerConnection второй аргумент в конструкторе необязательный: [{RtpDataChannels: true}] является обязательным, если вы используете Chrome или Opera. Следующим шагом является создание предложения для другого партнера. Добавьте следующий код в ваш файл client.js —
//setup a peer connection with another user
connectToOtherUsernameBtn.addEventListener("click", function () {
var otherUsername = otherUsernameInput.value;
connectedUser = otherUsername;
if (otherUsername.length > 0) {
//make an offer
myConnection.createOffer(function (offer) {
console.log();
send({
type: "offer",
offer: offer
});
myConnection.setLocalDescription(offer);
}, function (error) {
alert("An error has occurred.");
});
}
});
//when somebody wants to call us
function onOffer(offer, name) {
connectedUser = name;
myConnection.setRemoteDescription(new RTCSessionDescription(offer));
myConnection.createAnswer(function (answer) {
myConnection.setLocalDescription(answer);
send({
type: "answer",
answer: answer
});
}, function (error) {
alert("oops...error");
});
}
//when another user answers to our offer
function onAnswer(answer) {
myConnection.setRemoteDescription(new RTCSessionDescription(answer));
}
//when we got ice candidate from another user
function onCandidate(candidate) {
myConnection.addIceCandidate(new RTCIceCandidate(candidate));
}
Вы можете видеть, что когда пользователь нажимает кнопку «Установить соединение», приложение делает предложение SDP другому партнеру. Мы также устанавливаем обработчики onAnswer и onCandidate . Наконец, давайте реализуем функцию openDataChannel (), которая создает наш dataChannel. Добавьте следующий код в ваш файл client.js —
//creating data channel
function openDataChannel() {
var dataChannelOptions = {
reliable:true
};
dataChannel = myConnection.createDataChannel("myDataChannel", dataChannelOptions);
dataChannel.onerror = function (error) {
console.log("Error:", error);
};
dataChannel.onmessage = function (event) {
console.log("Got message:", event.data);
};
}
//when a user clicks the send message button
sendMsgBtn.addEventListener("click", function (event) {
console.log("send message");
var val = msgInput.value;
dataChannel.send(val);
});
Здесь мы создаем dataChannel для нашего соединения и добавляем обработчик событий для кнопки «отправить сообщение». Теперь откройте эту страницу в двух вкладках, войдите в систему с двумя пользователями, установите соединение и попробуйте отправлять сообщения. Вы должны увидеть их в выводе консоли. Обратите внимание, что приведенный выше пример протестирован в Opera.
Теперь вы можете видеть, что RTCDataChannel является чрезвычайно мощной частью WebRTC API. Есть много других вариантов использования этого объекта, таких как одноранговые игры или обмен файлами через торрент.
