1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
Programación
sobre Redes
Unidad 2
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
Procesos
Un proceso es una instancia en ejecución de un
programa. Cada proceso tiene su propio espacio de
memoria y recursos asignados por el sistema operativo.
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
Comunicación
Características
Cada proceso se ejecuta de forma
independiente, con su propio
espacio de memoria. Esto implica
que un error en un proceso rara vez
afecta a otro.
Crear y gestionar procesos requiere
más recursos y tiempo, ya que cada
proceso necesita su propio espacio
de memoria.
La comunicación entre procesos se
realiza mediante mecanismos como
pipes, sockets o colas de mensajes.
Esto es más complejo y suele ser
más lento debido a la falta de
memoria compartida.
Abrir varias aplicaciones en nuestro sistema
operativo, como un editor de texto, un
navegador y un reproductor de música. Cada
una de estas aplicaciones se ejecuta en un
proceso distinto. Si el editor de texto falla, los
otros programas seguirán funcionando.
Aislamiento Overhead Mayor
Ejemplo
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
Hilos
Un hilo es la unidad básica de ejecución dentro de un
proceso. Los hilos comparten el mismo espacio de
memoria y recursos del proceso, lo que permite una
comunicación directa y eficiente entre ellos.
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
Sincronización
Características
Todos los hilos de un proceso comparten la
misma memoria, lo que permite una
comunicación rápida, pero también requiere
mecanismos de sincronización (por ejemplo,
locks) para evitar conflictos.
La creación de un hilo es más rápida
y consume menos recursos que la
creación de un proceso.
Debido a la memoria compartida, es
fundamental coordinar el acceso a
recursos comunes para evitar
condiciones de carrera.
En una aplicación de edición de video,
diferentes hilos pueden encargarse de
reproducir el video, aplicar efectos y realizar la
codificación, trabajando en paralelo dentro del
mismo proceso para mejorar el rendimiento sin
necesidad de crear procesos independientes.
Memoria Compartida Overhead Menor
Ejemplo
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
¿Qué es la concurrencia?
Concurrencia es la capacidad de un sistema para manejar múltiples tareas al mismo
tiempo (aparente). No necesariamente significa que se estén ejecutando exactamente al
mismo segundo (eso sería paralelismo), sino que el sistema puede ir cambiando de una
tarea a otra rápidamente, dando la ilusión de simultaneidad.
Ejemplo: Imaginemos que somos un mozo en una cafetería (un solo hilo de ejecución) y
tenemos 5 mesas que nos piden cosas. No podemos atenderlas todas a la vez, pero sí
podemos:
● Anotar la orden de la mesa 1
● Mientras el café se prepara, ir a la mesa 2
● Tomar su orden
● Mientras esperamos la comida de la mesa 1, llevamos la bebida a la mesa 3
Estamos siendo concurrentes: gestionamos varias tareas sin hacerlas todas al mismo
tiempo.
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
¿Qué es la asincronía?
Asincronía significa que una operación puede comenzar ahora y terminar más
adelante, sin detener el flujo principal del programa.
En Node.js, cuando hacemos algo que tarda (cómo leer un archivo o consultar una API), lo
hacemos de forma asíncrona. Es decir:
● Mandamos a hacer la tarea
● Mientras tanto, seguimos ejecutando otras líneas de código
● Cuando termina, Node.js nos avisa (por ejemplo, con un callback)
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
¿Qué es el Event Loop?
El Event Loop (bucle de eventos) es el mecanismo que permite a Node.js ejecutar código
de forma no bloqueante usando un solo hilo.
¿Cómo funciona?
1. Ejecuta el código principal línea por línea (fase "síncrona").
2. Si encuentra algo asíncrono (como lectura de archivo, consulta HTTP), lo deriva a un
componente externo (por ejemplo, el sistema operativo).
3. Cuando esa tarea termina, el event loop la mete en una cola de tareas pendientes.
4. Cuando Node.js termina el código actual, revisa esa cola y ejecuta esas funciones
(callbacks, etc.).
Imaginemos al event loop como un asistente que:
● Recibe tareas
● Las ordena
● Y las ejecuta en el momento adecuado, sin detenerse por ninguna.
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
¿Por qué esto es útil en Node.js ?
Node.js no bloquea mientras espera operaciones lentas cómo leer archivos o consultar
bases de datos. En lugar de crear un nuevo hilo (como en otros lenguajes), usa el event
loop y asincronía para hacer más con menos.
Opciones para Paralelismo en Node.js:
➢ child_process: Permite crear procesos hijos independientes. Cada proceso hijo tiene
su propio espacio de memoria y se comunica con el proceso principal mediante IPC
(comunicación entre procesos). Es ideal para tareas que deben aislarse.
➢ worker_threads: Permite crear hilos (workers) dentro del mismo proceso para
ejecutar tareas intensivas en CPU. Estos hilos comparten memoria, lo que facilita la
comunicación, pero requieren sincronización para evitar conflictos.
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
1
0
1
0
1
0
0
Opción para el Proyecto FTSApp
Después de evaluar ambos enfoques, vamos a continuar con el método child_process para el
proyecto FTSApp.
Razones de la elección:
● Aislamiento y estabilidad: Cada conexión se maneja en un proceso independiente, lo que
minimiza el riesgo de que un error en una conexión afecte a las demás.
● Facilidad de depuración: Los procesos hijos tienen un entorno aislado, lo que facilita la
identificación y solución de problemas sin interferir con el proceso principal.
● Simplicidad en la implementación: Aunque los Worker Threads son más eficientes en
términos de recursos para tareas CPU-intensivas, nuestro caso de uso principal (gestión de
conexiones y mensajes simples) se beneficia del aislamiento que ofrecen los procesos hijos sin
requerir una sincronización compleja.
● Escalabilidad: En un entorno de producción, manejar conexiones en procesos separados
permite distribuir la carga entre varios núcleos o incluso máquinas, aprovechando
mecanismos de balanceo de carga.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en server.js
Importación de child_process:
● Se añade la línea const { fork } = require('child_process');
● Propósito: Permite crear procesos hijos que ejecuten otro archivo (en este caso, worker.js), lo que
proporciona aislamiento y manejo concurrente de conexiones.
Creación del Proceso Hijo con fork:
● Dentro del callback del servidor, al establecerse una conexión, se ejecuta:
const child = fork('./worker.js');
● Propósito: Cada vez que un cliente se conecta, se crea un proceso hijo independiente que se
encargará de procesar los datos enviados por ese cliente. Esto ayuda a aislar cada conexión y evita
que un error en una conexión afecte a las demás.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en server.js
Envío de Datos al Proceso Hijo:
● Se utiliza el evento socket.on('data', ...) para escuchar los datos que llegan del cliente.
● Dentro de ese callback, se envían los datos al proceso hijo con: child.send(data.toString());
● Propósito: Transferir el procesamiento de datos al proceso hijo, lo que permite que el proceso
principal se concentre en manejar las conexiones sin bloquearse en operaciones intensivas.
Recepción de Respuestas desde el Proceso Hijo:
● Se añade un manejador para el evento child.on('message', ...):
child.on('message', (message) => { socket.write(message); });
● Propósito: El proceso hijo procesa el mensaje (por ejemplo, convirtiéndolo a mayúsculas) y envía
una respuesta. Esta respuesta se reenvía al cliente, demostrando la comunicación bidireccional
entre el proceso principal y el hijo.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en server.js
Manejo del Cierre de Conexión:
● Al detectar que el cliente ha finalizado la conexión socket.on('end', ...), se llama a child.kill() para
terminar el proceso hijo.
● Propósito: Evitar procesos huérfanos y liberar recursos, asegurando que cada proceso hijo sólo
esté activo mientras su cliente esté conectado.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Código en worker.js
Este archivo es invocado desde el servidor principal server.js usando child_process.fork(). Actúa como un
proceso independiente, especializado en tareas de procesamiento (en este caso por ahora, transformar
texto a mayúsculas).
process.on('message', (message) => {
● Este evento escucha los mensajes enviados desde el proceso padre (el servidor).
● message contiene el contenido enviado desde server.js usando child.send(...)
● Esto es parte del mecanismo de IPC (Inter-Process Communication) entre el padre y el hijo.
console.log(`Worker: Recibido mensaje: ${message}`);
● Simple console.log() para que veamos que recibió el worker.
● Es útil para debuguear o para mostrar cómo fluye la comunicación entre procesos.
const processed = message.toUpperCase();
● Acá se hace el "procesamiento" simulado.
● Podría ser cualquier lógica compleja: análisis, búsqueda, cifrado, etc.
● En este caso, simplemente convierte el texto a mayúsculas usando .toUpperCase().
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Código en worker.js
process.send(`Respuesta procesada: ${processed}`);
● Envía la respuesta de vuelta al servidor server.js mediante process.send(...).
● En el padre, eso se recibe con:
worker.on('message', (response) => {
socket.write(response);
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en client.js
Módulo readline:
● Propósito: Permite leer datos de la consola de forma interactiva, como si fuera un input de un
formulario, pero en terminal: const readline = require('readline');
● Creamos una interfaz de entrada:
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
● Lo Nuevo: Antes, el cliente se conectaba y recibía datos sin dar la opción de interacción manual.
Ahora, el usuario puede escribir mensajes, lo que es esencial para aplicaciones en las que se
requiere retroalimentación del usuario (por ejemplo, un chat o una terminal remota).
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en client.js
Función preguntar():
● Propósito: Esta función utiliza rl.question() para solicitar al usuario que ingrese un mensaje. Luego,
dependiendo del input, envía ese mensaje al servidor o cierra la conexión.
● Lo Nuevo: Se implementa una función recursiva que se llama después de cada respuesta del
servidor para mantener la comunicación activa. Esto genera un ciclo donde el cliente:
○ Envía un mensaje.
○ Espera la respuesta del servidor.
○ Pide al usuario nuevamente un mensaje.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en client.js
Evento client.on('data', ...):
● Propósito: Detecta cuándo el servidor envía datos y, tras recibirlos, llama a la función preguntar()
para continuar la interacción.
client.on('data', (data) => {
console.log(`📨 Servidor: ${data.toString()}`);
preguntar();
● Lo Nuevo: En la versión base, el cliente solo recibía un mensaje y cerraba la conexión. Ahora, se
vuelve a invocar la función que solicita input al usuario, permitiendo conversaciones continuas.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en client.js
Manejo de Eventos 'close' y 'error':
● Propósito: Garantiza que, en caso de que el servidor cierre la conexión o se produzca un error, la
interfaz de entrada se cierre adecuadamente y se informe al usuario.
client.on('close', () => {
console.log('🔒 Conexión cerrada por el servidor.');
rl.close();
});
client.on('error', (err) => {
console.error('❌ Error en el cliente:', err.message);
rl.close();
});
● Lo Nuevo: El manejo de estos eventos es importante para proteger la aplicación y asegurarse de
que la sesión interactiva se cierre de forma ordenada si ocurre un problema.
1
0
1
0
0
1
0
0
1
0
1
1
0
1
1
1
1
0
0
1
0
1
0
1
0
0
1
0
1
0
1
0
Explicación Nuevo Código en client.js
Persistencia de la Conexión:
● Propósito: En lugar de cerrar la conexión inmediatamente después de recibir un mensaje (como en
la versión base), se permite que el usuario envíe múltiples mensajes
● Lo Nuevo: La conexión solo se cierra cuando el usuario escribe "salir", lo que posibilita una
interacción continua.

Programacion sobre Redes - Unidad el libroloool

  • 1.
  • 2.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 Procesos Un proceso esuna instancia en ejecución de un programa. Cada proceso tiene su propio espacio de memoria y recursos asignados por el sistema operativo.
  • 3.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 Comunicación Características Cada proceso seejecuta de forma independiente, con su propio espacio de memoria. Esto implica que un error en un proceso rara vez afecta a otro. Crear y gestionar procesos requiere más recursos y tiempo, ya que cada proceso necesita su propio espacio de memoria. La comunicación entre procesos se realiza mediante mecanismos como pipes, sockets o colas de mensajes. Esto es más complejo y suele ser más lento debido a la falta de memoria compartida. Abrir varias aplicaciones en nuestro sistema operativo, como un editor de texto, un navegador y un reproductor de música. Cada una de estas aplicaciones se ejecuta en un proceso distinto. Si el editor de texto falla, los otros programas seguirán funcionando. Aislamiento Overhead Mayor Ejemplo
  • 4.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 Hilos Un hilo esla unidad básica de ejecución dentro de un proceso. Los hilos comparten el mismo espacio de memoria y recursos del proceso, lo que permite una comunicación directa y eficiente entre ellos.
  • 5.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 Sincronización Características Todos los hilosde un proceso comparten la misma memoria, lo que permite una comunicación rápida, pero también requiere mecanismos de sincronización (por ejemplo, locks) para evitar conflictos. La creación de un hilo es más rápida y consume menos recursos que la creación de un proceso. Debido a la memoria compartida, es fundamental coordinar el acceso a recursos comunes para evitar condiciones de carrera. En una aplicación de edición de video, diferentes hilos pueden encargarse de reproducir el video, aplicar efectos y realizar la codificación, trabajando en paralelo dentro del mismo proceso para mejorar el rendimiento sin necesidad de crear procesos independientes. Memoria Compartida Overhead Menor Ejemplo
  • 6.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 ¿Qué es laconcurrencia? Concurrencia es la capacidad de un sistema para manejar múltiples tareas al mismo tiempo (aparente). No necesariamente significa que se estén ejecutando exactamente al mismo segundo (eso sería paralelismo), sino que el sistema puede ir cambiando de una tarea a otra rápidamente, dando la ilusión de simultaneidad. Ejemplo: Imaginemos que somos un mozo en una cafetería (un solo hilo de ejecución) y tenemos 5 mesas que nos piden cosas. No podemos atenderlas todas a la vez, pero sí podemos: ● Anotar la orden de la mesa 1 ● Mientras el café se prepara, ir a la mesa 2 ● Tomar su orden ● Mientras esperamos la comida de la mesa 1, llevamos la bebida a la mesa 3 Estamos siendo concurrentes: gestionamos varias tareas sin hacerlas todas al mismo tiempo.
  • 7.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 ¿Qué es laasincronía? Asincronía significa que una operación puede comenzar ahora y terminar más adelante, sin detener el flujo principal del programa. En Node.js, cuando hacemos algo que tarda (cómo leer un archivo o consultar una API), lo hacemos de forma asíncrona. Es decir: ● Mandamos a hacer la tarea ● Mientras tanto, seguimos ejecutando otras líneas de código ● Cuando termina, Node.js nos avisa (por ejemplo, con un callback)
  • 8.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 ¿Qué es elEvent Loop? El Event Loop (bucle de eventos) es el mecanismo que permite a Node.js ejecutar código de forma no bloqueante usando un solo hilo. ¿Cómo funciona? 1. Ejecuta el código principal línea por línea (fase "síncrona"). 2. Si encuentra algo asíncrono (como lectura de archivo, consulta HTTP), lo deriva a un componente externo (por ejemplo, el sistema operativo). 3. Cuando esa tarea termina, el event loop la mete en una cola de tareas pendientes. 4. Cuando Node.js termina el código actual, revisa esa cola y ejecuta esas funciones (callbacks, etc.). Imaginemos al event loop como un asistente que: ● Recibe tareas ● Las ordena ● Y las ejecuta en el momento adecuado, sin detenerse por ninguna.
  • 9.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 ¿Por qué estoes útil en Node.js ? Node.js no bloquea mientras espera operaciones lentas cómo leer archivos o consultar bases de datos. En lugar de crear un nuevo hilo (como en otros lenguajes), usa el event loop y asincronía para hacer más con menos. Opciones para Paralelismo en Node.js: ➢ child_process: Permite crear procesos hijos independientes. Cada proceso hijo tiene su propio espacio de memoria y se comunica con el proceso principal mediante IPC (comunicación entre procesos). Es ideal para tareas que deben aislarse. ➢ worker_threads: Permite crear hilos (workers) dentro del mismo proceso para ejecutar tareas intensivas en CPU. Estos hilos comparten memoria, lo que facilita la comunicación, pero requieren sincronización para evitar conflictos.
  • 10.
    1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 0 Opción para elProyecto FTSApp Después de evaluar ambos enfoques, vamos a continuar con el método child_process para el proyecto FTSApp. Razones de la elección: ● Aislamiento y estabilidad: Cada conexión se maneja en un proceso independiente, lo que minimiza el riesgo de que un error en una conexión afecte a las demás. ● Facilidad de depuración: Los procesos hijos tienen un entorno aislado, lo que facilita la identificación y solución de problemas sin interferir con el proceso principal. ● Simplicidad en la implementación: Aunque los Worker Threads son más eficientes en términos de recursos para tareas CPU-intensivas, nuestro caso de uso principal (gestión de conexiones y mensajes simples) se beneficia del aislamiento que ofrecen los procesos hijos sin requerir una sincronización compleja. ● Escalabilidad: En un entorno de producción, manejar conexiones en procesos separados permite distribuir la carga entre varios núcleos o incluso máquinas, aprovechando mecanismos de balanceo de carga.
  • 11.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen server.js Importación de child_process: ● Se añade la línea const { fork } = require('child_process'); ● Propósito: Permite crear procesos hijos que ejecuten otro archivo (en este caso, worker.js), lo que proporciona aislamiento y manejo concurrente de conexiones. Creación del Proceso Hijo con fork: ● Dentro del callback del servidor, al establecerse una conexión, se ejecuta: const child = fork('./worker.js'); ● Propósito: Cada vez que un cliente se conecta, se crea un proceso hijo independiente que se encargará de procesar los datos enviados por ese cliente. Esto ayuda a aislar cada conexión y evita que un error en una conexión afecte a las demás.
  • 12.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen server.js Envío de Datos al Proceso Hijo: ● Se utiliza el evento socket.on('data', ...) para escuchar los datos que llegan del cliente. ● Dentro de ese callback, se envían los datos al proceso hijo con: child.send(data.toString()); ● Propósito: Transferir el procesamiento de datos al proceso hijo, lo que permite que el proceso principal se concentre en manejar las conexiones sin bloquearse en operaciones intensivas. Recepción de Respuestas desde el Proceso Hijo: ● Se añade un manejador para el evento child.on('message', ...): child.on('message', (message) => { socket.write(message); }); ● Propósito: El proceso hijo procesa el mensaje (por ejemplo, convirtiéndolo a mayúsculas) y envía una respuesta. Esta respuesta se reenvía al cliente, demostrando la comunicación bidireccional entre el proceso principal y el hijo.
  • 13.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen server.js Manejo del Cierre de Conexión: ● Al detectar que el cliente ha finalizado la conexión socket.on('end', ...), se llama a child.kill() para terminar el proceso hijo. ● Propósito: Evitar procesos huérfanos y liberar recursos, asegurando que cada proceso hijo sólo esté activo mientras su cliente esté conectado.
  • 14.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Código enworker.js Este archivo es invocado desde el servidor principal server.js usando child_process.fork(). Actúa como un proceso independiente, especializado en tareas de procesamiento (en este caso por ahora, transformar texto a mayúsculas). process.on('message', (message) => { ● Este evento escucha los mensajes enviados desde el proceso padre (el servidor). ● message contiene el contenido enviado desde server.js usando child.send(...) ● Esto es parte del mecanismo de IPC (Inter-Process Communication) entre el padre y el hijo. console.log(`Worker: Recibido mensaje: ${message}`); ● Simple console.log() para que veamos que recibió el worker. ● Es útil para debuguear o para mostrar cómo fluye la comunicación entre procesos. const processed = message.toUpperCase(); ● Acá se hace el "procesamiento" simulado. ● Podría ser cualquier lógica compleja: análisis, búsqueda, cifrado, etc. ● En este caso, simplemente convierte el texto a mayúsculas usando .toUpperCase().
  • 15.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Código enworker.js process.send(`Respuesta procesada: ${processed}`); ● Envía la respuesta de vuelta al servidor server.js mediante process.send(...). ● En el padre, eso se recibe con: worker.on('message', (response) => { socket.write(response);
  • 16.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen client.js Módulo readline: ● Propósito: Permite leer datos de la consola de forma interactiva, como si fuera un input de un formulario, pero en terminal: const readline = require('readline'); ● Creamos una interfaz de entrada: const rl = readline.createInterface({ input: process.stdin, output: process.stdout, ● Lo Nuevo: Antes, el cliente se conectaba y recibía datos sin dar la opción de interacción manual. Ahora, el usuario puede escribir mensajes, lo que es esencial para aplicaciones en las que se requiere retroalimentación del usuario (por ejemplo, un chat o una terminal remota).
  • 17.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen client.js Función preguntar(): ● Propósito: Esta función utiliza rl.question() para solicitar al usuario que ingrese un mensaje. Luego, dependiendo del input, envía ese mensaje al servidor o cierra la conexión. ● Lo Nuevo: Se implementa una función recursiva que se llama después de cada respuesta del servidor para mantener la comunicación activa. Esto genera un ciclo donde el cliente: ○ Envía un mensaje. ○ Espera la respuesta del servidor. ○ Pide al usuario nuevamente un mensaje.
  • 18.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen client.js Evento client.on('data', ...): ● Propósito: Detecta cuándo el servidor envía datos y, tras recibirlos, llama a la función preguntar() para continuar la interacción. client.on('data', (data) => { console.log(`📨 Servidor: ${data.toString()}`); preguntar(); ● Lo Nuevo: En la versión base, el cliente solo recibía un mensaje y cerraba la conexión. Ahora, se vuelve a invocar la función que solicita input al usuario, permitiendo conversaciones continuas.
  • 19.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen client.js Manejo de Eventos 'close' y 'error': ● Propósito: Garantiza que, en caso de que el servidor cierre la conexión o se produzca un error, la interfaz de entrada se cierre adecuadamente y se informe al usuario. client.on('close', () => { console.log('🔒 Conexión cerrada por el servidor.'); rl.close(); }); client.on('error', (err) => { console.error('❌ Error en el cliente:', err.message); rl.close(); }); ● Lo Nuevo: El manejo de estos eventos es importante para proteger la aplicación y asegurarse de que la sesión interactiva se cierre de forma ordenada si ocurre un problema.
  • 20.
    1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 Explicación Nuevo Códigoen client.js Persistencia de la Conexión: ● Propósito: En lugar de cerrar la conexión inmediatamente después de recibir un mensaje (como en la versión base), se permite que el usuario envíe múltiples mensajes ● Lo Nuevo: La conexión solo se cierra cuando el usuario escribe "salir", lo que posibilita una interacción continua.