Websockets – ¡Comunicación instantanea!

¡Bienvenidos un día más a un nuevo rootie queridos amigos! Es viernes y aunque venimos con un día de retraso, aquí estamos de nuevo. Hoy vengo a hablar de una tecnología que aplicada a PHP tiene muchísimos detractores, pero que personalmente encuentro muy interesante, estamos hablando de los WebSockets.

Sockets, lo que hay que saber.

Como siempre, antes explicar que son los websockets y que podemos hacer con ellos, tenemos que entender que es un socket (en este caso un socket TCP).

Socket designa un concepto abstracto por el cual dos programas pueden intercambiar cualquier flujo de datos de manera fiable y ordenada. Los sockets TCP constituyen el mecanismo para la entrega de paquetes de datos. Un socket queda definido por un par de direcciones IPs con su puerto y un protocolo. – Wikipedia

Fácil, ¿no?. Para aquellos que habéis leído la definición y os habéis quedado igual que como estabais, podemos simplificar a que un socket es un canal de comunicación.

Dicho así parece poca cosa, ya que toda conexión a internet es un canal de comunicación en si misma, pero, si nos paramos a pensar un momento en como internet funciona, puede que veáis su uso (¡o no!).

Entendiendo el sistema Request-Response.

Internet esta construido siguiendo la filosofía de la petición – respuesta (request – response). Esto es que el cliente pide al servidor contenido y este le devuelve y se muestra al usuario de forma estática. Hasta que el cliente no vuelva a interactuar (hacer click, refrescar, etc.) el contenido será el mismo.

Esto hacía que las webs no tuviesen ningún dinamismo y necesitasen de la interacción del usuario a cada momento. Hacia 2005 con ajax y junto a estrategias como el long pooling esto empezó a cambiar. Pero estas dos técnicas no nos proveen de una comunicación en tiempo real, ademas hacían uso de HTTP, con lo cual tenian un alto grado de latencia. Para solucionar esto, debemos recurrir a los websockets.

Websockets, ¿wut?

Websockets es protocolo de comunicación, que nos proporciona canales con duplex completo sobre una única conexión TCP. Este protocolo esta diseñado para implementarse en navegadores servidores web.

La especificación del protocolo Websocket define ws wss como dos nuevos esquemas de identificador de recursos unificados (URI) para conexiones no encriptadas y encriptadas, respectivamente. Además del nombre del esquema, el resto de componentes del URI se definen con la sintaxis genérica de URI, pero no soporta el hastag (#) para fragmentos.

Una de las ventajas que podemos obtener de los websockets es que la única relación que tiene con HTTP, es el handhsake al realizar la conexión.

websockets-again
Websockets, Websockets, Websockets, Websockets, Websockets

En resumen, permite realizar una conexión permanente y en tiempo real ente cliente y servidor haciendo posible el envío de información en cualquier momento por ambas partes. Esto hace de websockets una tecnología realmente util a la hora de plantear aplicaciones en tiempo real como un chat, estadísticas. etc.

Negociación.

Para crear una conexión, el cliente envía una petición de negociación (handshake). Al igual que las peticiones HTTP, cada linea especifica una cabecera y su valor.

handshake-websockets
No, no es este el saludo que usamos

Respuesta del servidor:

Los 8 bytes con valores numéricos que acompañan a los campos Sec-WebSocket-Key1 y Sec-WebSocket-Key2 son tokens aleatorios que el servidor utiliza para crear un token de 16 bytes para confirmar que ha leído correctamente la petición de negociación del cliente.

La negociación o handshake se construye concatenando los números que acompañan al primer campo, y dividiéndolo por el número de espacios en blanco en el propio campo. Esto mismo se repite para el segundo campo. Los dos números resultantes se concatenan entre sí y con los 8 bytes que van después de los campos. El resultado final es una suma MD5 de la cadena concatenada.

Opciones de implementación.

PHP implementa nativamente el uso de sockets, y hoy por hoy la mejor forma de implementares mediante el uso de y stream_socket_server.

Cliente.

Aquí podemos ver ejemplos de como realizar una petición HTTP con sockets:

Servidor.

La extension de Stream ofrece una forma sencilla para crear servidores con la función stream_socket_server(). Esta función toma una especificación de socket como primer argumento, con el mismo formato de cadena pasado el cliente.

Ejecutar un servidor implica al menos los siguientes puntos:

  1. Bind un socket, le dice al SO que queremos que los paquetes de la red lleguen a la interfaz de red y el puerto del socket.
  2. Comprobar si la conexión entrante esta disponible
  3. Aceptar la conexión entrante con stream_socket_accept.
  4. Enviar una respuesta (útil) al cliente
  5. Cerrar la conexión o dejar al cliente cerrarla
  6. Volver al punto 2.

 

Aquí tenemos un ejemplo de un servidor que devuelve el mensaje pasado:

Podemos ejecutarlo con el siguiente comando:

Conclusion

Con este pequeño ejemplo de cliente servidor quería mostraros las bases de la implementación en PHP para gestionar conexiones via sockets. Pero siendo sinceros se pueden encontrar hoy en día varias alternativas ya creadas y testeadas por miles de personas, como pueden ser:

Critica al uso de websockets en PHP.

Básicamente hay una gran parte de la comunidad de PHP que no ven el uso de websockets como algo beneficioso. Esta critica viene fundada en la propia naturaleza de PHP, ya que según muchos críticos opinan que los scripts de PHP no estan diseñados para ejecutarse indefinidamente, cosa que puede pasar cuando ejecutamos un servidor de sockets.

Esto puede traer problemas derivados en el aumento de uso de recursos por parte de PHP, pero hablando desde mi propia experiencia, he tenido corriendo un servidor basado en Ratchet en un VPS pequeñito, dando conexiones a cientos de usuarios en una pequeña red social durante los últimos 3 años y solo he tenido que matar el proceso manualmente 1 única vez.

sockets tres años corriendo
not bad at all

Y con esto nos despedimos por hoy, espero que hayais disfrutado (y aprendido) leyendo el post de hoy tanto como yo he disfrutado escribiéndolo.

Como siempre para cualquier duda, pregunta, comentario, soborno o amenaza, podéis usar los comentarios o en nuestras redes sociales Facebook y Twitter.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *