2012-02-02 7 views
11

¿Es posible detectar el tipo de un mensaje de búfer de protocolo en bruto (en el byte [])memorias intermedias del Protocolo de detectar el tipo de mensaje prima

Tengo una situación en la que un punto final puede recibir mensajes diferentes y necesitan ser capaces para detectar el tipo antes de que pueda deserializarlo.

estoy usando

+0

Solo utilizaría múltiples puntos finales. La sobrecarga de funciones es lo suficientemente torpe en los lenguajes de programación, y mucho menos en los servicios de red. – millimoose

+0

Gracias, este es mi plan de copia de seguridad :) –

Respuesta

14

No se puede detectar el tipo de forma aislada, ya que la especificación protobuf no agrega ningún dato a la secuencia para esto; Sin embargo, hay un número de maneras de hacer esto fácil, dependiendo del contexto:

  • un tipo de unión (como se ha mencionado por Jon) abarca una gama de escenarios
  • herencia (específico para protobuf neto) puede ser versátil - puede tener un tipo de mensaje base, y cualquier número de tipos de mensajes concretos
  • puede utilizar un prefijo para indicar el tipo de entrada

el último enfoque es realmente muy valioso en el caso de TCP prima corrientes; esto es en el cable idéntico al tipo de unión, pero con una implementación diferente; decidiendo de antemano que 1 = Foo, 2 = Bar, etc. (exactamente como lo hace para el enfoque de tipo de unión), puede usar SerializeWithLengthPrefix para escribir (especificando el 1/2/etc como el número de campo), y el no genérico TryDeserializeWithLengthPrefix para leer (esto es en Serializer.NonGeneric en v1 API, o en TypeModel en v2 API), puede proporcionar un mapa de tipos que resuelve los números a tipos y, por lo tanto, deserializa el tipo correcto. Y para adelantarse a la pregunta "¿por qué es esto útil con las transmisiones TCP?" - porque: en una corriente TCP en curso, usted necesita para usar los métodos WithLengthPrefixde todos modos, para evitar leer en exceso la transmisión; así que es mejor que obtengas el identificador de tipo gratis!

Resumen:

  • tipo de unión: fácil de implementar; el único inconveniente es tener que verificar cuál de las propiedades es no nula
  • herencia: fácil de implementar; puede usar polimorfismo o discriminador para manejar "¿y ahora qué?"
  • prefijo de tipo: un poco más complicados de implementar, pero permite una mayor flexibilidad, y tiene cero sobrecarga en flujos TCP
+0

Hola, gracias por la respuesta detallada. He logrado el resultado deseado utilizando Serializer.SerializeWithLengthPrefix & Serializer.NonGeneric.TryDeserializeWithLengthPrefix Me gustaría usar RuntimeTypeModel para evitar tener atributos en mis clases. El modelo.SerializeWithLengthPrefix parece funcionar como se esperaba, pero no pude encontrar un equivalente de TryDeserializeWithLengthPrefix en RuntimeTypeModel. El model.DeserializeWithLengthPrefix parece esperar un tipo. ¿Cómo debo lograr el equivalente de TryDeserializeWithLengthPrefix usando el modelo? Usando la versión 2.0.0.480 Nuget –

+0

He cambiado mi código para agregarlo y agregar definiciones de modelo a RuntimeTypeModel.Default y puedo usar TryDeserializeWithLengthPrefix sin atributos. Antes de crear un nuevo modelo con TypeModel.Create Problema resuelto Gracias –

+0

@Yavor en TypeModel, es simplemente DeserializeWithLengthPrefix, junto con TypeResolver. ¡No estoy seguro de dónde fue el Try! Lo buscaré detrás de los cojines en el sofá, ahí es donde terminan la mayoría de las cosas. –

12

Una opción típica-protobuf neta es tener un mensaje envoltorio para actuar como un "tipo de opción" o unión discriminada. Puede tener una enumeración (una por tipo de mensaje) y un mensaje que contenga un campo con el tipo de mensaje, y luego un campo opcional por tipo de mensaje.

Esto se describe en la documentación de Protobuf como "union type".

3

Usted podría envolverlo como este. Donde los datos mantendrían el mensaje real.

message MyCustomProtocol { 
    required int32 protocolVersion = 1; 
    required int32 messageType = 2; 
    bytes data = 3; 
} 

Una regla general para los protocolos es incluir una versión de protocolo. Estará muy contento de tenerlo una vez que tenga clientes antiguos y nuevos.

Cuestiones relacionadas