Estoy tratando de implementar una robusta biblioteca TCP que permita a los usuarios seleccionar un protocolo de aplicación o implementar uno propio y simplemente "conectarlos" al cliente/servidor.¿Cuál es el patrón correcto para implementar el encuadre TCP? ¿Es una pila de filtros?
Por protocolo me refiero simplemente a la capacidad de definir cómo la secuencia debe enmarcarse en mensajes.
Estoy utilizando las bibliotecas integradas de asynch TCP para el resto de la pila y he desarrollado un cliente que genera eventos cada vez que se establece una conexión, se leen o escriben datos o se produce una excepción.
Tengo dos opciones para implementar el protocolo de trama. El primero, que ya está funcionando, es ampliar la clase de cliente y anular el evento de datos recibidos, de modo que esto solo se produzca cuando se haya recibido un mensaje completo. (Es decir, bajo el capó guardo los datos brutos del zócalo y, según el protocolo, decido cuándo tengo un mensaje completo y luego elevo el evento de datos recibidos). Esto es similar a cómo funciona la biblioteca Nito.Asynch.
El problema con este enfoque es que significa que cada nuevo protocolo requiere una nueva implementación del cliente. Prefiero que el cliente mantenga una pila interna de filtros que se pueden agregar o eliminar.
Cuando los datos se reciben en el socket, se pasan al primer filtro que almacena en búfer hasta que se haya decidido transmitir un mensaje completo con el encabezado o los metadatos eliminados. Esto se pasa luego al siguiente filtro en la pila, etc.
De esta manera los filtros se pueden definir/desarrollar independientemente de la biblioteca y se pueden inyectar en el cliente según la configuración (en tiempo de ejecución).
Para lograr esto, pensé en definir los filtros como pares de implementaciones de System.IO.Stream (entrantes y salientes) que son mantenidas internamente por el cliente.
La lectura de datos del socket se escribiría en la secuencia entrante inferior en la pila. Los datos leídos de esa secuencia se escribirían en la siguiente secuencia, etc. hasta que la última transmisión (parte superior de la pila) devuelva datos y el cliente los devuelva. (Mi plan era usar la función CopyTo() de Stream).
Los datos escritos en el cliente se escribirían en la secuencia saliente superior y se copiarían en la pila hasta que la secuencia saliente inferior escriba en el socket subyacente.
Obviamente, hay mucho que considerar y estoy tratando de entender la forma correcta de comportarme como un objeto Stream. Ejemplo: ¿Qué hago cuando alguien llama a Flush() ...?
¿Es esta una buena manera de lograr esto o estoy reinventando la rueda aquí?
La biblioteca Nito.Asynch
Lo único que puedo señalar aquí es que el "IProtocolFilter" no sigue el estándar .net de e Normalmente, utilizas EventHandler y creas una clase que hereda EventArgs. –
Peter