En este capítulo, aprenderemos a crear Sockets utilizando node.js
Antes que nada, crearemos un directorio llamado networking, en el que iremos añadiendo los distintos archivos.js que aparecen en el capítulo. Empezamos con el primer archivo, 'net-watcher.js'. En ella llamamos a los módulos Nojde.js fs y net:
Nos fijamos en la función callback dada a createServer(), esta función hace principalmente tres cosas:
- La primera, reportar que la conexión se ha establecido.
- Empieza a escuchar por si se producen cambios en el documento establecido.
- Escucha hasta que se haya realizado el cierre de la conexión.
Se pasa el puerto al que queremos conectarnos (60300). Para ejecutar abriremos tres terminales, en la primera ejecutaremos watch -n 1 touch target.txt, en la segunda node net-watcher.js target.txt y en la tercera nc localhost 60300. Aquí vemos el resultado de la conexión que se establece:
Lo que haremos ahora es modificar el fichero net-watcher.js, cambiando la línea en la que se pasa el puerto, escribiendo '/tmp/watcher.sock':
En la consola ejecutamos node net-watcher-unix.js target.txt, lo que hace es esperar por 'suscribers'. En otra consola ejecutamos nc -U /tmp/watcher.sock y vemos como espera a que hayan cambios en target.txt, y vemos como en la otra consola, el 'suscriber' se conecta:
En este apartado, lo que haremos es modificar net-watcher.js. Seguiremos los pasos de libro y guardaremos el fichero como net-watcher-json-service.js:
Este fichero lo ejecutaremos en la terminal junto con target.txt, mientras que en otra terminal hacemos nc localhost 60300, y funcionará de forma parecida al fichero anterior, pero esta vez aparece el tipo o la forma y el archivo que estamos pasando como argumento junto al comando:
En este apartado, creamos un programa de cliente en Node.js para recibir mensajes JSON de nuestro programa servidor. Aquí vemos el programa que lo llamamos net-watcher-json-client.js:
Este programa usa net.connect para crear un conexión de cliente al puerto 60300, y entonces espera por datos. Ejecutamos node net-watching-json-client.js, vemos como espera por el archivo target.txt. Si hacemos un touch de target.txt, aparecerá los datos del archivo. Hay que tener en cuenta que para que esto funcione, el programa del servidor debe estar ejecutándose:
Aquí implementaremos un servicio de prueba que divide a propósito un mensaje en múltiples partes:
Lo ejecutamos en la terminal: node test-json-service.js. Este servicio de prueba difiere de nuestro programa de servicio anterior en algunos aspectos. En lugar de configurar un observador del sistema de archivos, como hicimos para el servicio real, aquí solo enviamos el primer fragmento predeterminado de inmediato. Mientras ejecutamos y vemos como está esperando, ejecutamos en otra terminal el programa del cliente. Esto nos da un error porque el mensaje no está completo:
El programa que hicimos en la sección anterior tenía una debilidad en el código del cliente, no sacaba las entradas. Cualquier mensaje que llega como eventos de datos múltiples da error. El programa cliente tiene dos trabajos que hacer, uno es sacar datos entrantes en mensajes, y el otro es manejar cada mensaje cuando llegue.
Para no tener que meter ambos trabajos en un mismo programa, la solución correcta es transformar al menos uno de ellos en un módulo Node.js. Crearemos un módulo que maneje la pieza de entrada para que el programa principal pueda obtener mensajes completos.
En este apartado, vamos a exponer a LDJClient como un módulo. Empezamos por crear dentro del directorio de trabajo networking, otro directorio llamado lib. Dentro de este directorio creamos el fichero ldj-client.js:
El objeto module.exports es el puente entre el código del módulo y el mundo exterior.
En este apartado, modificamos el cliente para usarlo en lugar de leer directamente desde el flujo TCP, llamando a este fichero net-watcher-ldj-client.js:
Es similar al programa net-watcher-json-client. La principal diferencia es que en lugar de enviar buffers de datos directamente a JSON.parse, este programa se basa en el módulo LDJClient para producir eventos de mensaje.
Ejecutamos en una terminal el servicio de prueba (node test-json-service.js) y en otra terminal el nuevo cliente para conectarse:
Ahora tendremos un servidor y un cliente que utilizan un formato de mensaje personalizado para comunicarse de manera fiable.
Mocha es un popular marco de pruebas para Node.js. Cuenta con varios estilos diferentes para describir nuestras pruebas. Debemos instalar instalado npm y después de esto, debemos desarrollar una prueba unitaria para la clase LDJClient.
Hemos ejecutado el comando npm init -y en nuestro directorio networking, y directamente se nos ha creado por defecto un archivo package.json. Seguidamente hemos introducido el comando: npm install --save-dev --save-exact [email protected]. Después de instalar esto, haciendo un cat package.json, podemos comprobar que se ha descargado correctamente:
La etiqueta --save-exact le dice a npm que versión específica queremos instalar. Por defecto, npm usa el versionamiento semántico para encontrar la mejor versión disponible de un paquete.
El número de la versión consta de tres partes unidas por puntos, la versión principal, la versión menor y el parche.
- Si la modificación del código no introduce o elimina ninguna funcionalidad, se incrementa la versión del parche.
- Si la modificación introduce funcionalidad pero no elimina o altera la funcionalidad ya existente, se incrementa la versión menor y se resetea el parche.
- Si la modificación altera o rompe la funcionalidad existente, se incrementa la versión principal y se resetea la versión menor y el parche.
Hemos creado un directorio /networking/test para mantener el código relacionado con la prueba. Hemos llamado al archivo ldj-client-test.js:
Para ejecutar las pruebas usando npm, debemos añadir una entrada al fichero package.json:
Visualizando el contenido del fichero package.json, quedaría así:
Luego, ejecutando npm test, se realiza la ejecución de prueba:
Este ejercicio lo que nos pide es añadir dos pruebas unitarias:
- La primera, para para un solo mensaje que se divide en dos o más eventos de datos desde el stream.
- La segunda, que pase un null al constructor LDJClient, y lance un error.
Lo que hacemos es editar el fichero 'ldj-client-test.js', añadiendo las pruebas:
Es importante, añadir en el constructor, la opcion para comprobar si el stream es null, y en caso de que sea así, aparezca el error por pantalla:
Vemos, al ejecutar las pruebas, que funcionan correctamente:
La primera pregunta nos dice: El LDJClient ya maneja el caso en el que una cadena JSON con el formato correcto se divide en varias líneas. ¿Qué sucede si los datos entrantes no son una cadena JSON con el formato correcto?
- El programa fallaría porque no sabe manejar ese tipo de errores.
La segunda pregunta nos pide añadir una prueba que envíe un evento de datos que no sea JSON.
- Como hicimos con anterioridad, añadimos la prueba en el fichero 'ldj-client-test.js', un assert que emita un stream que no sea JSON:
Comprobamos que la prueba funciona correctamente:
La tercera pregunta nos dice: ¿Qué sucede si el último evento de datos completa un mensaje JSON, pero sin la nueva línea final?
- Lo que sucede es que el programa fallaría, porque no sabe manejar ese tipo de errores.
La cuarta pregunta nos pide escribir un caso en el que el objeto de flujo envíe un evento de datos que contenga JSON pero no una nueva línea, seguido de un evento de cierre.
- Creamos una prueba unitaria en 'ldj-client-test.js' donde añadimos el stream que emite el evento de cierre:
- Modificamos el constructor añadiendo un stream.on donde comprueba si se encuentra el '}' final, y no el salto de línea:
Comprobamos que funciona correctamente:
La última pregunta nos dice: ¿Debería LDJClient emitir un evento cercano para sus listeners?
- Debería emitirlo cuando sus listeners no estén enviando nada y también cuando hayan avisado de que cierran la conexión.
59be09997e8787c40907becf28f695b95e5d3248