protocolo - segmento tcp
¿Cómo debo marcar el final de un paquete TCP? (6)
En una aplicación cliente / servidor donde se enviarán datos de texto de distinta longitud entre el cliente y el servidor, ¿cómo debo marcar el final de un paquete que se está enviando? Por ejemplo, cuando el servidor está recibiendo datos de paquete de un cliente, ¿cómo sabe el servidor que el paquete del cliente se ha recibido por completo?
¿Es más común decirle al servidor la longitud total del paquete que va a recibir antes de los datos o tener algo marcando el final del paquete?
Algunos de los datos enviados solo tendrán unos pocos caracteres y algunos podrían tener miles de caracteres.
Estructure su paquete de tal manera que incluya un campo de longitud al comienzo.
Si el emisor conoce la longitud, el emisor debe indicar la longitud por adelantado como un campo de tamaño fijo, seguido de los datos de tamaño variable.
La ventaja frente a un marcador de cola es que el receptor puede optimizar la cantidad esperada de datos, por ejemplo, asignar un búfer del tamaño correcto. Por ejemplo, el almacenamiento a través de protocolos TCP / IP tiene el mismo problema sobre TCP / IP que usted. En esos casos, los encabezados proporcionan la longitud de los datos esperados posteriormente.
Más adelante en el camino, puede encontrar otros bits para poner en su "encabezado". Se alegrará de tener alguna estructura para hacer crecer su propio protocolo de capa 5.
TCP proporciona una secuencia continua de datos. TCP se implementa utilizando paquetes, pero el objetivo de TCP es ocultarlos.
Piense en ello como si fuera un muro sobre el que desea dibujar. La pared está hecha de ladrillos. Los ladrillos se pegan con mortero y se aplica yeso para que la superficie de la pared se vuelva lisa. Los ladrillos son los paquetes de IP, TCP es el yeso.
Entonces ahora tienes tu túnel TCP enyesado liso y quieres agregar algo de estructura en él. Desea dibujar cuadros, para que sus dibujos se mantengan separados el uno del otro. Esto es lo que quiere hacer: agregar un poco de estructura "administrativa" (recuadros alrededor de los dibujos) a sus datos.
Muchos protocolos usan el concepto de packet
, que es un conjunto de datos que comienza con un encabezado administrativo de formato fijo. El encabezado contiene suficiente información para decidir dónde termina el paquete; por ejemplo, incluye la longitud del paquete. HTTP lo hace, con un encabezado Content-Length
, o (con HTTP / 1.1) con la "codificación de transferencia fragmentada" donde los datos se dividen en uno o varios mini-paquetes, cada uno con un encabezado simple que consiste exactamente en un mini-paquete- indicación de longitud
Otra forma es tener una secuencia de terminación especial que no puede aparecer en "datos normales". Si sus datos son texto, entonces podría usar un byte de valor cero como terminador.
Otra forma es usar datos con terminación propia. Estos son datos estructurados de tal forma que usted puede saber en cualquier momento si se ha alcanzado el final del elemento. Por ejemplo, los datos XML se organizan como pares anidados de marcadores como <foo>...</foo>
. Cuando se llega al marcador final ( </foo>
), usted sabe que el elemento está terminado.
Toma tus señales de HTTP.
Utilice una secuencia de caracteres de terminador, o especifique una longitud en algún lugar del encabezado del mensaje, o use una combinación inteligente de ambos.
Como hace HTTP: los encabezados terminan con CR-LF-CR-LF. Si hay datos más allá de los encabezados, la longitud de los datos está en uno de los encabezados.
Si te sientes particularmente audaz, puedes buscar el uso de sockets SCTP en lugar de sockets TCP.
Tenga cuidado con la basura si codifica la longitud al principio. Por ejemplo, si usa 4 bytes binarios para la longitud y una sonda externa envía una solicitud HTTP, es probable que termine con un gran número y esperando por siempre (sin mencionar la asignación de un búfer que podría bloquear su programa). Envío la longitud dos veces cada uno a través de una función diferente y los comparo (por ej. ~ Len y len xor 0x139AF321). También debe establecer un máximo en caso de que alguien intente bloquear su programa activamente. Si obtengo una mala longitud, simplemente cierro la conexión.
Esto está por encima de un HMAC si su tráfico está encriptado.