Pregunta

Esta es una especie de rama de mi otra pregunta.Léelo si quieres, pero no es necesario.

Básicamente, me di cuenta de que para poder usar BeginReceive() de C# de manera efectiva en mensajes grandes, necesito (a) leer primero la longitud del paquete y luego leer exactamente esa cantidad de bytes o (b) usar un delimitador de fin de paquete.Mi pregunta es: ¿alguno de estos está presente en los buffers de protocolo?No los he usado todavía, pero al repasar la documentación no parece que haya un encabezado de longitud o un delimitador.

Si no, ¿qué debo hacer?¿Debería simplemente crear el mensaje y luego agregarle un prefijo/sufijo con el encabezado de longitud/delimitador EOP?

¿Fue útil?

Solución

Debe incluir el tamaño o el marcador final en su protocolo.No hay nada integrado en los sockets basados ​​en flujo (TCP/IP) aparte de admitir un flujo indefinido de octetos divididos arbitrariamente en paquetes separados (y los paquetes también pueden dividirse en tránsito).

Un enfoque simple sería que cada "mensaje" tuviera un encabezado de tamaño fijo, incluyera tanto una versión del protocolo como un tamaño de carga útil y cualquier otro dato fijo.Luego, el contenido del mensaje (carga útil).

Opcionalmente, se puede agregar un pie de página del mensaje (tamaño fijo) con una suma de verificación o incluso una firma criptográfica (dependiendo de sus requisitos de confiabilidad/seguridad).

Conocer el tamaño de la carga útil le permite seguir leyendo una cantidad de bytes que será suficiente para el resto del mensaje (y si una lectura se completa con menos, realizar otra lectura para los bytes restantes hasta que se haya recibido el mensaje completo).

Tener un indicador de fin de mensaje también funciona, pero necesita definir cómo manejar su mensaje que contiene esa misma secuencia de octetos...

Otros consejos

Las disculpas por llegar tarde a la fiesta. Soy el autor de protobuf-net, una de las implementaciones de C #. Para uso de la red, usted debe considerar los métodos "[de] SerializeWithLengthPrefix" - de esa manera, se manejará automáticamente las longitudes para usted. Hay ejemplos en la fuente.

No voy a entrar en gran detalle en una entrada antigua, pero si quieres saber más, añadir un comentario y voy a volver a usted.

Estoy de acuerdo con Matt en que un encabezado es mejor que un pie de página para Protocol Buffers, por la razón principal de que, como PB es un protocolo binario, es problemático crear un pie de página que no sea también una secuencia de mensajes válida.Muchos protocolos basados ​​en pie de página (normalmente los de EOL) funcionan porque el contenido del mensaje está en un rango definido (normalmente 0x20 - 0x7F ASCII).

Un enfoque útil es hacer que su código de nivel más bajo simplemente lea los buffers del socket y los presente en una capa de estructura que ensambla mensajes completos y recuerda los parciales (presento un enfoque asíncrono para esto (usando el CCR). aquí, aunque para un protocolo de línea).

Para mantener la coherencia, siempre puedes definir tu mensaje como un mensaje PB con tres campos:un entero fijo como longitud, una enumeración como tipo y una secuencia de bytes que contiene los datos reales.Esto mantiene transparente todo el protocolo de red.

TCP / IP, así como UDP, los paquetes incluyen alguna referencia a su tamaño. El cabecera IP contiene un campo de 16 bits que especifica la longitud de la cabecera IP y de datos en bytes. El href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol" rel="nofollow cabecera TCP noreferrer"> contiene un campo de 4 bits que especifica el tamaño de la cabecera TCP en 32- palabras de bits. El UDP cabecera contiene un campo de 16 bits que especifica la longitud de la cabecera UDP y de datos en bytes.

Aquí está la cosa.

El uso de los enchufes estándar de ejecución de la fábrica en Windows, ya sea que esté utilizando el espacio de nombres System.Net.Sockets en C # o el material nativo en Winsock Win32, usted nunca ve los / las cabeceras TCP / UDP IP. Estas cabeceras se despojaron de modo que lo que se obtiene cuando se lee la toma de la carga útil es real, es decir, los datos que se envió.

El patrón típico de todo lo que he visto y hecho usando sockets siempre es que se define una cabecera de nivel de aplicación que precede a los datos que desea enviar. Como mínimo, esta cabecera debe incluir el tamaño de los datos a seguir. Esto le permitirá leer cada "mensaje" en su totalidad sin tener que adivinar en cuanto a su tamaño. Usted puede conseguir tan elegante como usted quiera con él, por ejemplo, los patrones de sincronización, CRC, versión, tipo de mensaje, etc., pero el tamaño del "mensaje" es todo lo que realmente necesidad.

Y por si sirve de algo, se recomienda usar un encabezado en lugar de un delimitador de fin de paquete. No estoy seguro de si hay una desventaja a signficant el delimitador EOP, pero la cabecera es el enfoque utilizado por la mayoría de los protocolos IP que he visto. Además, apenas se parece más intuitivo para mí para procesar un mensaje desde el principio, en lugar de esperar a que algún patrón que aparezca en mi corriente para indicar que mi mensaje es completa.

EDIT: he hecho más que tomar conciencia del proyecto Google Protocol Buffers. De lo que puedo decir, es un esquema de serialización / de-serialización binaria para WCF (estoy seguro de que es una simplificación excesiva). Si está utilizando WCF, usted no tiene que preocuparse por el tamaño de los mensajes que se envían porque la instalación de cañerías de WCF se encarga de esto detrás de las escenas, que es probablemente por qué no se ha encontrado nada relacionado con la longitud del mensaje en el Protocolo documentación de buffers. Sin embargo, en el caso de tomas de corriente, sabiendo el tamaño ayudará enormemente a cabo como se ha discutido anteriormente. Mi suposición es que va a serializar sus datos usando los búferes de protocolo y luego virar en cualquier encabezado de la aplicación te ocurrió antes de enviarlo. En el lado de recepción, se le salga de la cabecera y luego de-serializar el resto del mensaje.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top