2010-12-28 14 views
10

que tienen una matriz de bytes de esta manera:Cómo dividir y unir matriz en C++ para UDP?

lzo_bytep out; // my byte array 
size_t uncompressedImageSize = 921600; 

out = (lzo_bytep) malloc((uncompressedImageSize + 
      uncompressedImageSize/16 + 64 + 3)); 
wrkmem = (lzo_voidp) malloc(LZO1X_1_MEM_COMPRESS); 

// Now the byte array has 802270 bytes 
r = lzo1x_1_compress(imageData, uncompressedImageSize, 
     out, &out_len, wrkmem); 

Cómo puedo dividir en partes más pequeñas debajo de 65.535 bytes (la matriz de bytes es una imagen grande que quiero enviado a través de UDP que tiene límite superior de 65.535 bytes) y luego unir esos pequeños trozos de nuevo en una matriz continua?

Respuesta

41

El problema al hacer esto es que los paquetes UDP pueden llegar o solicitarse, o pueden descartarse. Use TCP para esto; para eso es para.

+1

Pero aun así, me gustaría hacer esto con UDP. Solo envío toda la imagen una vez y luego envío solo los píxeles que han cambiado, por lo que los siguientes paquetes serán más pequeños y se ajustarán en un solo paquete UDP. Necesito UDP porque es más rápido que TCP y necesito velocidad. –

+23

@Richard: No podrá implementar una conexión que haga esto correctamente que funcione más rápido que TCP. Abra una conexión TCP para enviar sobre el gran fragmento inicial y luego use UDP para las actualizaciones (suponiendo que si alguna de las actualizaciones se pierde o destruye, puede recuperarse de eso; los paquetes UDP pueden perderse o destruirse). Esto es lo que hacen los servidores de juegos que necesitan este tipo de baja latencia, es decir, los archivos de sonido y tales se transfieren a través de TCP, pero las posiciones de jugador y tal se transmiten a través de UDP (es decir, servidores CounterStrike). –

+2

Verdadero en teoría. Menos en la práctica. –

13

No tiene que "dividir" la matriz. Solo tienes que señalar diferentes partes de él.

Suponiendo que está utilizando una función de escritura UDP() típica, toma varios argumentos. Uno de ellos es un puntero al buffer y el otro es la longitud.

Si usted quiere conseguir los primeros 65535 bytes, el tampón está a wrkmem y la longitud es 65535.

Para el segundo 65535 bytes, el tampón está a wrkmem + 65535 y su longitud es de 65535.

El tercer 65535 bytes, su búfer está en wrkmem + 2 * 65535 y su longitud es 65535.

¿Obtiene?

(Dicho esto, los otros carteles son correctos. Debería usar TCP).

Por otro lado, cuando desee volver a unirse a la matriz, debe asignar suficiente memoria para todo, luego utilice una función de copia como memcpy() para copiar los fragmentos que llegan a su posición correcta. Recuerde que UDP puede no entregar las piezas en orden y no entregarlas todas.

+1

+1 - por supuesto, ninguno de los lados podrá detectar si un paquete llega fuera de servicio o si se cae por completo. Por lo tanto, el OP necesitará implementar su propio mecanismo para entregar estas tareas. –

+13

mira el lado positivo: aprenderá mucho sobre la aritmética de punteros tratando de volver a implementar su propia implementación de TCP. –

+1

Este es un buen punto ... aunque espero que no se retire de mi cuenta de cheques :) –

1

Es posible que desee probar un middleware basado en mensajes como ØMQ y alimentar toda la imagen comprimida como un solo mensaje y hacer que el middleware se ejecute de forma asincrónica y administrar la reimpresión a la mayor velocidad posible. Proporciona una API compatible con el socket BSD, por lo que puede ser fácil migrar el código y le permite intercambiar fácilmente entre varios protocolos de transporte subyacentes según sea necesario.

Otros sistemas de mensajes están disponibles.

void my_free (void *data, void *hint) 
{ 
    free (data); 
} 

    /* ... */ 

size_t uncompressedImageSize = 921600, compressedImageSize = 0; 
size_t out_len = (uncompressedImageSize + uncompressedImageSize/16 + 64 + 3); 
lzo_bytep out = (lzo_bytep)malloc (out_len); 
lzo_voidp wkrmem = (lzo_voidp)malloc (LZO1X_1_MEM_COMPRESS); 
zmq_msg_t msg; 

rc = lzo1x_1_compress (imageData, uncompressedImageSize, 
         out, &compressedImageSize, wrkmem); 
assert (compressedImageSize > 0); 
rc = zmq_msg_init_data (&msg, out, compressedImageSize, my_free, NULL); 
assert (rc == 0); 
/* Send the message to the socket */ 
rc = zmq_send (socket, &msg, 0); 
assert (rc == 0);