domingo, 26 de julio de 2015

Receta C# No. 5-26: Escritura y Lectura Entre Procesos

Índice

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Named pipes (tubierías nombradas)
3.2 Clase NamedPipeServerStream
3.3 Clase NamedPipeClientStream
4. Práctica: Código C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

Alcanzamos la última receta de la serie de recetas C# dedicadas a Archivos, Directorios, y Entrada y Salida. En esta ocasión vamos a construir una aplicación basada en consola para permitir a múltiples procesos comunicarse entre sí y ejecutar operaciones de lectura y escritura en conjunto. Para ello hemos de explorar y conocer las clases NamedPipeServerStream y NamedPipeClientStream para crear un servidor de escucha de conexiones y clientes de conexión para interacción mutua.

1. Problema

Requerimos intercomunicar dos procesos para el envío y recepción de datos.

2. Solución

El namespace System.IO.Pipes cuenta con dos clases diseñadas para permitir que dos procesos se puedan intercomunicar e intercambiar datos. Estas clases siguen el mecanismo de intercomunicación named pipes (o tuberías nombradas).

3. Discusción de la Solución

3.1 Named pipes (tuberías nombradas)

De acuerdo con [2] un named pipe (o tubería nombrada) es uno de los varios mecanismos para la intercomunicación de procesos. A diferencia de los unamed pipes (los cuales se ejecutan de forma anónima y durante el ciclo de vida del proceso), los named pipes, además de contar con un identificador específico, pueden persistir más allá de la ejecución de un proceso y el sistema puede programarse para eliminarlos cuando sea requerido.
Named pipes
Figura 1. Diagrama conceptual de Named pipes.
Y de acuerdo con [3], un nombre alternativo para los named pipes es FIFO [5] debido a que los datos que son escritos primero son los primeros en ser leídos.

3.2 Clase NamedPipeServerStream

La clase NamedPipeServerStream [6] (namespace System.IO.Pipes) pertmite la comunicación entre procesos en los modos: 
  • unidireccional, y 
  • bidireccional
Esta clase actúa como el servidor de escucha de conexiones desde uno o más clientes. Y como explican en [6]
"Named pipes can be used for interprocess communication locally or over a network."
Lo que quiere decir es que podemos intercomunicar procesos inter-máquina (local) e intermáquina (red).


Nota importante de límites de número máximo de named pipes en algunos sistemas operacionales
"For Windows XP Professional and Windows 2000 Server, a maximum of 10 pipes can simultaneously connect over the network."
Ejemplo de uso

Archivo C# UsoNamedPipeServerStream.cs [Enlace alternativo][Enlace alternativo]: 

Sobre la línea 15 de la instrucción using creamos una instancia de NamedPipeServerStream para representar el servidor de escucha de conexiones desde clientes. Con la llamada a WiatForConnection (línea 21) esperamos a que un cliente se conecte para empezar el proceso de envío de datos.

En el bloque try (líneas 25-34) efectuamos las siguientes tareas: 
  • Línea 28: Creación de un objeto StreamWriter para escribir datos desde la consola y enviarlos a los clientes conectados al servidor.
  • Línea 32: Leemos la entrada del usuario y la envíamos a los clientes.
En caso de que se produzca un problema en la conexión con el cliente, se lanzará una excepción IOException reportando la causa del error (línea 38).

Compilación: 

  1. csc /target:exe UsoNamedPipeServerStream.cs

Ejecución assembly

  1. .\UsoNamedPipeServerStream.exe

3.2 Clase NamedPipeClientStream

Con la clase NamedPipeClientStream [7] (namespace System.IO.Pipes) creamos clientes para conexiones a named pipes. Podemos crear n instancias de objetos NamedPipeClientStream para establecer conexión con el servidor manejado por una instancia de NamedPipeServerStream.

Las conexiones se llevan a cabo a través del método Connect [8]. Este método también cuenta con una versión sobrecargada asincrónica [9] para soporte de lectura y escritura asincrónicas entre procesos.

Ejemplo de uso

En la línea 15 creamos un objeto NamedPipeClientStream que se conectará con un named pipe con el identificador servidor. Con el método Connect esperamos a que haya una conexión disponible. En el bloque using creamos un objeto StreamReader para recibir los mensajes desde el named pipe servidor. Mostramos los mensajes enviados desde el servidor en la línea 34.

Compilación: 


  1. csc /target:exe UsoNamedPipeClientStream.cs

Ejecución Assembly


  1. .\UsoNamedPipeClientStream.exe

> Prueba de ejecución: 
Ejecución assemblies UsoNamedPipeServerStream.exe y UsoNamedPipeClientStream.exe
Animación 1. Ejecución assemblies UsoNamedPipeServerStream.exe y UsoNamedPipeClientStream.exe.

4. Práctica: Código C#

Afiancemos nuestro conocimiento diseñando una nueva aplicación consola para crear un servidor y un cliente y facilitar entre ellos la intercomunicación para el envío y recepción de mensajes.

En el punto de entrada de la aplicación, Main (líneas 11-26), determinamos en qué modo debe iniciarse la aplicación consola: cliente o servidor.


En el método IniciarServidorPipe (líneas 28-60) ocurren las siguientes operaciones: 
  • Línea 31: Instanciación de un objeto NamedPipeServerStream para la creación de un named pipe identificado como servidor.
  • Línea 35: Invocación de WaitForConnection para esperar conexiones desde un cliente.
  • Líneas 45-50: Ciclo for para enviar hasta 10 datos  desde servidor hacia el cliente.
  • Líneas 53-56: Ciclo for para recibir hasta 10 datos desde el cliente.
  • Línea 59: Cierre del named pipe servidor.
Respecto al método IniciarClientePipe
  • Línea 65: Instanciación de un objeto NamedPipeClientStream para conexión con un named pipe identificado como servidor.
  • Línea 68: Intento de conexión con el servidor con el método Connect.
  • Líneas 76-76Ciclo for para recibir hasta 10 datos desde el servidor.
  • Líneas 82-87: Ciclo for para enviar hasta 10 datos hacia el servidor.
  • Línea 90: Cierre del cliente con Close.
Compilcación: 

  1. csc /target:exe ServidorClienteNamedPipe.cs

Ejecución assembly

  1. .\ServidorClienteNamedPipe.exe

> Prueba de ejecución: 
Ejecución assembly ServidorClienteNamedPipe.exe
Animación 2. Ejecución assembly ServidorClienteNamedPipe.exe.

5. Conclusiones

Hemos aprendido que la intercomunicación entre procesos es muy sencilla. Esto gracias al uso de las clases NamedPipeServerStream y NamedPipeClienteStream, y al comprensión del mecanismo de intercomunicación de procesos pipe named (o tuberías nombradas).

Finalizamos esta serie de recetas C# de Archivos, Directorio, y Entrada y Salida. A partir de la siguiente serie nos centraremos en Procesamiento XML.

6. Glosario

  • Conexión
  • Dato
  • Intercomunicación
  • Name pipe
  • Proceso
  • Unamed pipe

7. Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: Named pipe - Wikipedia, the free encyclopedia - https://en.wikipedia.org/wiki/Named_pipe
[3]: Inter-process communication - Wikipedia, the free encyclopedia - https://en.wikipedia.org/wiki/Inter-process_communication
[4]: What is named pipe? - Definition from WhatIs.com - http://whatis.techtarget.com/definition/named-pipe
[5]: FIFO (computing and electronics) - Wikipedia, the free encyclopedia - https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)
[6]: NamedPipeServerStream Class (System.IO.Pipes) - https://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeserverstream(v=vs.110).aspx
[7]: NamedPipeClientStream Class (System.IO.Pipes) - https://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream(v=vs.110).aspx
[8]: NamedPipeClientStream.Connect Method (System.IO.Pipes) - https://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.connect(v=vs.110).aspx
[9]: NamedPipeClientStream.ConnectAsync Method (System.IO.Pipes) - https://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.connectasync(v=vs.110).aspx


V

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.