2010-12-28 4 views
10

Ho un array di byte come questo:Come dividere e unire array in C++ per 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); 

Come posso dividerlo in parti più piccole sotto 65.535 byte (l'array di byte è una grande immagine che voglio inviati su UDP che ha limite superiore 65.535 byte) e poi unire quei piccoli pezzi indietro in un array continuo?

risposta

41

Il problema con ciò è che i pacchetti UDP possono arrivare o essere ordinati o essere rilasciati. Usa TCP per questo; questo è quello che è per

+1

Ma ancora, mi piacerebbe farlo con UDP. Invio solo l'intera immagine una volta quindi invio solo i pixel che sono stati modificati in modo che i seguenti pacchetti siano più piccoli e si inseriscano in un unico pacchetto UDP. Ho bisogno di UDP perché è più veloce del TCP e ho bisogno di velocità. –

+23

@Richard: non si sarà in grado di implementare una connessione che lo faccia correttamente e che sia più veloce di TCP. Aprire una connessione TCP per inviare il grande blocco iniziale e quindi utilizzare UDP per gli aggiornamenti (supponendo che se uno qualsiasi degli aggiornamenti viene perso o distrutto, è possibile ripristinarlo; i pacchetti UDP possono essere persi o distrutti). Questo è ciò che fanno i server di gioco che hanno bisogno di questo tipo di bassa latenza - cioè i file audio e così via vengono trasferiti su TCP, ma le posizioni dei giocatori e tali sono trasmesse su UDP (cioè i server CounterStrike). –

+2

È vero in teoria. Meno in pratica. –

13

Non è necessario "dividere" l'array. Devi solo indicare in diverse parti di esso.

Supponendo che si stia utilizzando una tipica funzione di scrittura() UDP, sono necessari diversi argomenti. Uno di questi è un puntatore al buffer e l'altro è la lunghezza.

Se si desidera ottenere i primi 65535 byte, il buffer è al wrkmem e la lunghezza è 65535.

Per il secondo 65535 byte, il buffer è a wrkmem + 65535 e la lunghezza è 65535.

Il terzo 65535 byte, il tuo buffer è a wrkmem + 2 * 65535 e la tua lunghezza è 65535.

Provalo?

(Detto questo, gli altri poster sono corretti. Dovresti usare TCP).

Dall'altro lato, quando si desidera riconnettere l'array, è necessario allocare memoria sufficiente per l'intera operazione, quindi utilizzare una funzione di copia come memcpy() per copiare i blocchi in arrivo nella loro posizione corretta. Ricorda che UDP potrebbe non consegnare i pezzi in ordine e potrebbe non consegnarli tutti.

+1

+1 - ovviamente nessuna delle due parti sarà in grado di rilevare se un pacchetto arriva fuori servizio o viene completamente eliminato. Pertanto l'OP dovrà implementare il proprio meccanismo per la consegna di questi compiti. –

+13

guarda il lato positivo: imparerà molto sull'aritmetica dei puntatori cercando di reimplementare la sua implementazione TCP. –

+1

Questo è un buon punto ... anche se spero che non sia il mio conto corrente con cui si sta ritirando :) –

1

Si potrebbe desiderare di provare un middleware basato su messaggi come ØMQ e alimentare l'intera immagine compressa come un messaggio e avere il middleware eseguito in modo asincrono e gestire la riconsegna alla massima velocità possibile. Fornisce un'API compatibile con socket BSD e quindi può essere facile migrare il codice e consente di scambiare facilmente tra i vari protocolli di trasporto sottostanti, come richiesto.

Sono disponibili altri sistemi di segnalazione.

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);