WebRTC - Envío de mensajes
Ahora creemos un ejemplo simple. En primer lugar, ejecute el servidor de señalización que creamos en el tutorial "servidor de señalización" a través de "servidor de nodo".
Habrá tres entradas de texto en la página, una para un inicio de sesión, otra para un nombre de usuario y otra para el mensaje que queremos enviar al otro par. Cree un archivo index.html y agregue el siguiente código:
<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>
También agregamos tres botones para iniciar sesión, establecer una conexión y enviar un mensaje. Ahora cree un archivo client.js y agregue el siguiente código:
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));
};
Puede ver que establecemos una conexión de socket a nuestro servidor de señalización. Cuando un usuario hace clic en el botón de inicio de sesión, la aplicación envía su nombre de usuario al servidor. Si el inicio de sesión es exitoso, la aplicación crea el objeto RTCPeerConnection y configura un controlador de candidatos de hielo que envía todos los candidatos de hielo encontrados al otro par. También ejecuta la función openDataChannel () que crea un dataChannel. Tenga en cuenta que al crear el objeto RTCPeerConnection, el segundo argumento en el constructor es opcional: [{RtpDataChannels: true}] es obligatorio si está utilizando Chrome u Opera. El siguiente paso es crear una oferta para el otro compañero. Agregue el siguiente código a su archivo 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));
}
Puede ver que cuando un usuario hace clic en el botón "Establecer conexión", la aplicación hace una oferta de SDP al otro par. También configuramos los controladores onAnswer y onCandidate . Finalmente, implementemos la función openDataChannel () que crea nuestro dataChannel. Agregue el siguiente código a su archivo 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);
});
Aquí creamos el canal de datos para nuestra conexión y agregamos el controlador de eventos para el botón "enviar mensaje". Ahora abra esta página en dos pestañas, inicie sesión con dos usuarios, establezca una conexión e intente enviar mensajes. Debería verlos en la salida de la consola. Tenga en cuenta que el ejemplo anterior se prueba en Opera.
Ahora puede ver que RTCDataChannel es una parte extremadamente poderosa de la API de WebRTC. Hay muchos otros casos de uso para este objeto, como los juegos de igual a igual o el intercambio de archivos basado en torrents.