martes, 5 de mayo de 2015

Web_RTC

WebRTC

Comenzamos con WebRTC. ¿Qué es webRTC y para que sirve?  WebRTC es una API(interfaz de programación de aplicaciones) que está siendo elaborada para permitir a las aplicaciones del navegador realizar llamadas de vozchat de vídeo y uso compartido de archivos P2P(Peer to Peer).

¿Por qué es tan importante webRTC? Los profesionales de las comunicaciones dicen que webRTC, va ser la tecnología del futuro principalmente porque es independiente de la plataforma(windows,linux,os...) Esto hace que cualquier usuario que use cualquier maquina sea capaz de comunicarse con otro.

En este tutorial, voy a intentar ser lo más claro posible para que la gente que este comenzando con estas tecnologías sean capaces de entenderlo. Recomiendo previamente que antes de leer mis explicaciones de como funciona webRTC, echen un vistazo al funcionamiento de simpleWebRTC, https://simplewebrtc.com/.

Bueno como en todos mis post publicados, voy a intentar ser lo más claro posible y vamos analizar el funcionamiento de webRTC en 4 PASOS sencillos.

PASO 0: Introducción a webRTC

PASO 1: Flujo de datos

PASO 2: Código javascript del cliente y del servidor de señalización.

PASO 3: Ejemplo de comunicación entre un Mac y un Windows.

*Nota: Todo el código de este tutorial y del anterior, lo podrás encontrar en:
https://github.com/graylinx/rtc

Comenzamos con el tutorial, en caso de que algo no sea entendido o este mal explicado publicarlo en el foro y lo debatiremos.

PASO 0: Introducción a webRTC

Lo primero y más importante que hay que entender en webRTC, es que necesitamos de un servidor de señalización para poder entablar una conversación. Una vez que ya obtengamos la información necesaria para poder hablar entre dos, el servidor de señalización se desvinculará y solo estaremos los Peer que queramos hablar. ¿Entonces es posible hablar mas de 2 Peer? Si es posible, pero nuestro tutorial es básico y se centra en la comunicación de 2 Peer.

¿Cómo funciona el establecimiento de la conexión? Pues utilizamos la API websocket que como ya explique en el post anterior, es una manera de establecer conexión bidireccional sin sobrecargas de gestión para obtener respuestas en tiempo real. Se basa en el protocolo TCP.
Durante la conexión y hasta el final del uso de la aplicación, utilizamos webRTC que permite a las aplicaciones del navegador realizar llamadas de voz, chat de video y uso compartido de archivos P2P sin plugins. WebRTC implenta tres APIs:
  1. MediaStream o GetUserMedia: Permite obtener streams de audio, video o combinaciones de ambos del dispositivo. Una vez obtenida la información de la cámara, la pantalla o el micrófono del usuario, podemos aplicarle efectos en el cliente, enviarla a nuestro servidor para almacenarla para cualquier tipo de aplicación social o podemos usar las siguientes APIs para enviar la información en tiempo real a otro usuario o incluso a varios usuarios.
  2. RTCPeerConnection: Esta API se encarga de realizar el streaming de video o audio, con todo lo que esto conlleva: procesar la señal, realizar la comunicación, ejecutar el code, administrar el ancho de banda, la seguridad, etc. Estas son tareas bastantes complejas y es API permite implementarlas, sin que el programador se tenga que preocupar por nada.
  3. RTCDataChannel: Dependiendo del tipo de aplicación que queramos, puede que necesitemos hacer streaming de otro tipo de datos que no sea video o audio. RTCDataChannel, realiza la comunicación bidireccional de cualquier tipo de datos entre pares, usando la misma API que websockets (la API utilizada para la comunicación bidireccional entre el cliente y el servidor). Permite que el flujo de datos sea fiable y la comunicación más lenta (TCP), o que no sea fiable y la comunicación sea más rápida (UDP).
Por último añadir como introducción de WeRTC, que tenemos versiones estables para Chrome escritorio, Chrome android, Firefox y Opera. Esta tecnología bajo mi punto de vista va ser clave para que JavaScript y HTML5 se conviertan en los lenguajes de desarrollo más usados para realizar aplicaciones móviles.

PASO 1: Esquema y análisis del flujo de datos

Comenzamos con lo realmente complicado de este tutorial. Vamos a intentar entender como funciona el siguiente diagrama de flujo de datos, ya que va ser clave para entender la práctica.

Vamos a ponernos ya en situación de un caso real: El PeerA va ser un ordenador Mac que quiere establecer una conexión con el PeerB que es un PC. Para ello se enfrentan a grandes dificultades como son los router NAT(IP Públicas/ IP Privadas), este es el verdadero problema de ipv4. Para solucionar el problema de las IP Privadas se inventaron los servidores STUN, para el caso de los routers Full Cone  y los servidores TURN para los routers Restricted Cone, Port Restricted Cone o Symmetric
Pero bueno poniéndonos en situación real, este problema nos influye si salimos de nuestra red, pero en nuestro caso vamos a simplificar la práctica y vamos a obviar los servidores STUN y TURN y nos vamos a centrar en WebRTC dentro de una LAN. Pos si alguien le interesa este tema, ya que le interesa probar webRTC desde red a otra, adjunto un link en el que se explica muy bien el problema que causa los NAT.
http://telefonia.blog.tartanga.net/2014/05/03/stun-turn-ice-upnp-alg-y-otros-el-lado-oscuro-de-la-telefonia-ip/

Continuamos entonces con el flujo de datos simplificado debido a que no vamos a salir de nuestra LAN. He intentado describir en una transparencia como se va a comportar webRTC a la hora de establecer conexión y en que consiste el server de señalización. Las lineas en rojo son mensajes que envía el server al cliente y las lineas azules mensajes que emitirá el cliente al server. Una vez que se complete todo este proceso podemos cerrar el servidor y comprobar si la conexión sigue existiendo entre los dos Peer.


En nuestro caso el Mac será el Peer iniciador, este concepto es muy importante en webRTC, ya que siempre tiene que haber un iniciador de la conexión que cree una habitación. El iniciador también será el encargado de realizar la llamada(offer) y el Peer2 que en nuestro caso es un PC será el que responda la contestación(answer) siempre y cuando entre en la misma habitación que hayan acordado previamente los dos Peers.

PASO 2: Código javascript del cliente y del servidor de señalización.

Una vez entendido la explicación de como se consiguen comunicar 2Peer que están en la misma red, vamos al código javascript que nos permite implentar lo que queremos hacer. Primero voy a empezar explicando el código del servidor de señalización que es muy simple comparado con el del cliente. Utilizamos la librería socket.io ya utilizada en la práctica anterior.

A grandes rasgos el servidor, cuyo fichero he llamado app.js, solo se tiene que encargar de recibir mensajes y reenviárselos a los peer.

Una vez que arrancamos el servidor con el comando node app.js en nuestra consola, lo primero que hace es inicializar estas variables y se queda escuchando en el puerto 8181esperando cualquier tipo de petición (req).
Consta de las siguientes variables:
app.js
Cuando un cliente decida hacer una petición Get: IP:PORT, el servidor enviará el archivo html con sus correspondiente script escrito en javascript donde estarán implementadas las APIs de webRTC. Entonces vamos a analizar que ficheros enviamos al cliente:
Lo primero del cliente es su documento html, al que he llamado index.html.
index.html
El html contiene tres fichero js que hacen referencia a la librería socket.io, a un fichero adapter.js que no vamos a profundizar en el y al fichero cliente.js que contiene todo el código necesario para hacer posible la comunicación webRTC.
Fichero cliente.js, si analizamos poco a poco de  lo que se compone este código, nada más arrancar el fichero procedente del servidor el cliente ejecuta el código cliente.js inicializando las siguientes variables:
cliente.js
Lo que hace el cliente es crear una habitación y enviar un mensaje al servidor, esta parte es la que se encarga las linea de la 53 a la 56 de la figura anterior.

Cuando al servidor le llega el mensaje del cliente ("create or join"), lo analiza y comprueba si es el primer o el segundo cliente, enviando diferentes mensajes dependiendo del cliente que haya llegado.
app.js
Ahora es cuando el cliente recibe un mensaje dependiendo de si es 1ºpeer o 2ºpeer. En caso de que sea 1ºPeer hace lo siguiente, haciendo uso del API getusermedia:
cliente.js
Si da el caso de que ya hay un peer en la habitación, al 2º cliente le llegaran un mensajes de tipo join, que el cliente recibirá y pondrá el canal listo para procesar las ofertas y enviar las respuestas, también haciendo uso del API getusermedia.
cliente.js

Una vez que todo este listo el cliente1 hará la llamada. No sin antes preparar la conexión a partir del API RTCPeerConexión. Donde el cliente iniciador enviará la oferta SDP al servidor y el servidor se la reenviará al cliente2, tal y como se mostraba en el esquema del PASO 1. Es entonces cuando el cliente2 hace el mismo procedimiento pero a la inversa (answer).

cliente.js
La recepción de estos mensajes en el servidor es algo muy simple, solamente se encarga de recibirlos y enviarlos.
app.js
Con esto podríamos entender por encima como se comporta el proceso de comunicación con el servidor de señalización, para poder entablar comunicación con otro Peer. Y ahora es cuando llega la esencia de esta tecnología. Una vez que dispongamos la información necesaria para poder comunicarnos con nuestro otro Peer, el servidor puede ser desvinculado, ya que no cumple ninguna función más que la mencionada. Esto nos permitirá no depender de servidores y no tener que ser escuchados por gente que no deseemos o simplemente por el hecho de hacer una web mucho más abierta y sin trabas.

¿Cómo no vamos a depender del servidor?  La prueba de que no dependemos para nada del servidor, esta por ejemplo en el chat que he implentado, utilizando el API RTCDataChannel. Para terminar la explicación del código cliente, voy a explicar como se comporta este APIs que tiene implementado webRTC, en el que consiste en una comunicación en tiempo real muy similar a la que ofrece websocket. La diferencia de websocket con datachanel esta en el protocolo de comunicaciones que utiliza "UDP" poco fiable, pero muy rápido. También se puede configurar para poder usar TCP en datachanel. Como vereís en la siguiente figura, simplemente tenemos que asignar el evento onclick al elemento "button" para que se active la función sendata, en la cual se inicializará la variable data con el valor del texto que le metamos en campo "sendTextarea". Por último como el peer1 sabe donde tiene que enviar la información, no necesita de ningún intermediario, es decir la comunicación es fluida entre el peer1 y el peer2.


cliente.js
PASO 3: Ejemplo de comunicación entre un Mac y un Windows en una misma red (LAN).

Para terminar el tutorial se me ha ocurrido mostrar un ejemplo de la interfaz gráfica de como hablan un Mac OS, con un PC. Para ello tenemos que editar primero la variable socket que se encuentra en el cliente.
cliente.js
y remplazarla por la ip pública que tenemos en nuestro router, que en mi caso es la:
terminal
cliente.js
Una vez inicializadas esta variable, lo único que tenemos que hacer es abrir la terminal y arrancar el server app.js
terminal
A continuación arrancaremos Mozilla en el Mac como peer iniciador, con la siguiente url: 192.168.1.13:8181 e introduciremos el nombre de la sala, en este caso sala1.
ORDENADOR MAC

Lo mismo debemos de hacer con el PC, pero ahora lo haremos desde un navegador chrome. Y esto es lo que nos aparece:


Como vemos, parece que el establecimiento de conexión esta ya terminado solo falta que el iniciador de a aceptar y que el PC escriba el mismo nombre de la sala y le de también a aceptar. Una vez que ambos estén dentro veremos los siguiente:
PC de R2D2
Mac de Darth Vader

Solo nos faltaría interrumpir el server y ver si es posible la comunicación (en la termina ctrl+c).


Este último paso os lo dejo a vosotros para que comprobéis que todo lo que os he explicado en este tutorial es cierto. Espero que os haya gustado y nos vemos en otra.

Un saludo. 

Mario.







martes, 28 de abril de 2015

P4 WEBSOCKETS

Practica HTML 5: chat con websockets.

Vamos a programar una aplicación web de chat entre multiples usuarios usando websocket, utilizando un servidor ws en Node.js.
Conceptos básicos:
¿Qué es websocket? Es una tecnología que proporciona un canal de comunicacion bidireccional sin sobrecargas de gestión para obtener respuestas en tiempo real. Se basa en el protocolo TCP.
¿Qué es node.js? Node.js es un entorno de programación en la capa del servidor basado en el lenguaje de programación Javascript.

Voy a intentar explicarlo en 4 pasos simples, para que gente sin mucha experiencia pueda desarrollar esta práctica.

PASO 0: Instalar node.js en nuestro ordenador, aquí publico el link donde poder descargarlo. https://nodejs.org/

PASO 1: Comunicación entre servidor y cliente a partir de la biblioteca socket.io.

PASO 2: Utilización de la librería de java (JQuery), para poder manipular de forma dinámica los elementos del árbol DOM.

PASO 3: Añadir un registro de usuarios, paro poder controlar que no se repitan “Nicks”.

Vamos a comenzar con el desarrollo de este tutorial, que bajo mi punto de vista es de los 4 post que llevo publicados el más sencillo y divertido.


PASO 0: Instalando node.js.

Una vez descargado el fichero de la web https://nodejs.org/, En primer lugar vamos a crear un package.json archivo que describe nuestro proyecto. Te recomiendo que lo coloques en un directorio vacío (lo llamaré por ejemplo chat).

En nuestro carpeta /chat tendremos que tener los siguientes archivos y ficheros:
-       Una carpeta node_modules, la cual no tendremos que tocar.
-        Un archivo package.json.


-       Un archivo app.js donde desarrollaremos la parte del server

-       Un archivo index.html donde se encontrara la parte del cliente.



 PASO 1: Comunicación cliente-server a partir de socket.io


¿Qué es socket.io? Socket.io es una librería JavaScript para comunicación web en tiempo real entre cliente y servidor.

En este PASO 1 vamos a tener que estar muy atentos a mis indicaciones para hacerlo funcionar. Como ya he dicho vamos a tener dos ficheros claves en esta practica, en mi caso los he llamado index.html y app.js. Vamos a ir desmenuzando el código para saber que hace cada linea. 


Comenzamos encendiendo el server y haciéndole escuchar en un puerto, en mi caso el 3000.


Las 5 primeras lineas son variables, que mas tarde usaremos para la comunicación, y la linea 7 es la que permite tener al servidor escuchando en el puerto 3000.

De la linea 9 a la 12 de nuestro fichero app.js, lo que hacemos es esperar una petición GET del cliente y responderle con el envío de un fichero index.html que todavía no tenemos implementado.

Continuamos con nuestro app.js y una vez explicada toda la reception y reenvio de mensajes nos meteremos con el fichero index.html que tendrá el cliente.

De la linea 14 a la 42, estaría todo el codigo neceario para terminar de implementar nuestra app.js, pero vamos a ir analizando que hace cada cosa. Bueno como ya he dicho socket.io es una librería de javascrip, por lo que si habéis hecho mis antiguos post os sonarán cosas. 

La línea 14 arranca el servidor y lo deja pacientemente encendido esperando algún tipo de mensaje. 

De la linea 16 a la 27, lo que se encarga el servidor es de recibir un mensaje INIT que tendrá que ser enviado por el cliente y reenviar un mensaje WELCOME con el fin de que el resto de clientes sepan de la conexión del cliente que se acaba de conectar.

De la linea 29 a la 33, el servidor gestiona los mensajes WRITER que le llegan de un cliente y los reenvía 'send writer' en forma de span al resto de clientes.

Por último de la linea  35 a la 39, el servidor estará atento por si algún cliente se desconecta, y en tal caso enviará a todos los clientes conectados al chat un mensaje LOGOUT, para que sepan que se ha ido del chat.

Aquí terminaríamos con nuestro server y ahora tendríamos que analizar lo que se encuentra en la parte cliente. Como ya hemos dicho el cliente hace una petición GET y el servidor le responde con un fichero.html, en nuestro caso index.html que va consistir en lo siguiente:


Para la parte del cliente lo primero, es hacer nuestra estructura html con su correspondiente css. Tener en cuenta que los identificadores van a ser claves a la hora de dar dinamismo a la pagina.

PASO 2. Utilización de la librería de java (JQuery), para poder manipular de forma dinámica los elementos del árbol DOM.


Lo primero que hacemos es, justo debajo de nuestra estructura html insertar dos scrip que hacen referencia el primero a la librería jQuery y el segundo a la librería socket.io.js. Luego insertamos un tercer scrip donde nombraremos a todos los id del html antes mencionados.

Este tercer scrip va ser el más importante ya que va ser el encargado de comunicarse con nuestro servidor. Vamos a ir analizando como envío el mensaje INIT y WRITER y como recibo el mensaje WELCOME, send writer y LOGOUT.



Si nos fijamos en la linea 95 es donde nos habíamos quedado antes y ahora le he implementado el envio de un mensaje INIT y la recepción de un mensaje WELCOME. LA recepción del welcome no tiene mucho misterio, pero el envío del INIT tiene algo que hace especial a node.js y es la bidirecionalidad que tiene con el servidor, es decir, el cliente le enviara un mensaje al server y si tenéis el código del server podeis ver que en caso de que no sea aceptado se comunicará con el cliente para decirle que el NICK no es correcto. Esto lo hace a partir de una función callback que si le dedicais un poco de tiempo lo entendereis sin problema.

Continuemos con la transmisión de mensajes WRITER y su recepción 'send writer'.


No hay mucho que añadir, si hemos entendido la funcionalidad del envio de INIT y recepción welcome, esto es más de lo mismo, lo único es que cuando recibo en send writer, le envio dos valores que son el nick de quien lo dice y el mensaje que envía en una tupla.

Por último entender la recepción del LOGOUT, que no es más que una recepción de mensaje más


Con esto tendríamos todo el código necesario, para hacer funcionar nuestro chat con un registro de usuarios y así poder permitir que no entren al chat dos clientes con el mismo Nick. En el PASO 3 no voy a añadir más código simplemente voy a matizar el código necesario para entender como es posible gestionar lo de los nick repetidos.

PASO 3: Código, para poder controlar que no se repitan “Nicks”.

Como ya he dicho todo el código de mi chat esta en las imágenes que he publicado, de hecho hay alguna imagen con código repetido.

Vamos a intentar explicar lo más “complicadillo” de este chat, que es que cuando nos registremos con un usuario que ya este en el chat no nos deje entrar.  

Bien esto va a estar en la parte del servidor, quien va almacenar un array con todos los nicks del server. Si miramos en el código de la figura_2 vemos que hay una variable llamada nicknames[], esta va ser un array de nombres. En el código de la figura_4 linea 18 cuando recibimos el INIT tenemos una condición que es: if (nicknames.indexOf(name) != -1)
Esta condición hace que si llega un nick repetido se cumpla y directamente se meta llamando a la función callback y salte nickError. Si no se cumple esta condición es que el nick no esta repetido entonces añadiremos a nuestro array como siempre hemos hecho.
nicknames.push(socket.nickname);

Por último cuando algún user salga del chat tiene que dejar el nick libre para que otro lo pueda usar y eso lo hacemos con la siguiente linea de codigo:
nicknames.splice(nicknames.indexOf(socket.nickname), 1);

Y hasta aquí nuestro tutorial, espero que les haya gustado y nos vemos detro de poco con otra tecnología de servidor, llamada webRTC, audio y video en tiempo real. Un saludo.