2012-08-24 11 views
6

In C avevo codice funzionante ma non avevo idea del perché funzionasse, quindi ho iniziato a riscriverlo in modo da poter effettivamente capire cosa sta succedendo.Come memorizzare l'output di recv()?

Fin qui tutto bene! Ho riscritto e sono sicuro al 90% che capisco tutto ciò che sta accadendo ora; il problema, tuttavia, è che non ho idea di come archiviare il blocco dati ricevuto da recv (databff) nel buffer pre-allocato (htmlbff).

Si consideri il seguente codice (si noti che ho messo a nudo questo giù un bel po ', in modo che include solo le nozioni di base, ad esempio, non ha memoria riallocazione o perdite di protezione, ecc ...):

#define BUFFERSIZE 4096 
#define MAXDATASIZE 256 

char *htmlbff, databff[MAXDATASIZE]; 
int c, i = BUFFERSIZE, q = 0;   
if(!(htmlbff = malloc(i))) 
{ 
    printf("\nError! Memory allocation failed!"); 
    return 0x00; 
} 
while((c = recv(sock, databff, MAXDATASIZE, 0)) > 0) 
{ 
    /*memory checks stripped out since they are irrelevent for this post*/ 
    /*store data to the appropriate area in htmlbff*/ 
    q += c;   
} 

Quindi (se Sto facendo tutto bene, e le cose stanno andando come penso che siano) c è la dimensione del frammento di dati corrente e q è la quantità totale di dati ricevuti finora (q viene incrementata di c ogni volta che il ciclo si ripete). Al momento sto usando q per la gestione della memoria (nel caso qualcuno si stia chiedendo) ma credo che avrà anche scopo nella soluzione a questo problema.

In ogni caso, la domanda che sto ponendo riguarda il secondo commento. Come posso archiviare correttamente i dati da recv in htmlbff?

risposta

2

Usa memcpy, e l'offset htmlbff da q:

memcpy(htmlbff + q, databff, c); 

È possibile simile recv direttamente in htmlbff:

c = recv(sock, htmlbff + q, MAXDATASIZE, 0)); 

Ma è bene mantenere un buffer separati, e in base al vostro codice completo , può rendere le cose più chiare.

Assicurarsi di aggiungere controlli contro BUFFERSIZE in modo da non copiare oltre i limiti di htmlbff. Hai detto che hai tolto la gestione dello realloc, quindi forse lo stai già gestendo.

I vostri nomi costanti sono un po 'di confusione, quando il buffering dei dati userei BUFFERSIZE per indicare la dimensione di ogni pezzo , vale a dire la dimensione del databff.

+0

Mi piace molto questa risposta grazie. Ho trovato questo più utile perché ora posso semplicemente saltare usando il buffer e scrivere direttamente in htmlbff. –

5

Utilizzare memcpy() per copiare (aggiungere) i dati allo htmlbff ma è inoltre necessario assicurarsi di non superare la dimensione di htmlbff. O interrompere il recupero dei dati quando i byte BUFFERSIZE sono stati ricevuti o utilizzare realloc() per estendere htmlbff per contenere più dati.

Ad esempio:

char* htmlbff; 
size_t htmlbff_size = BUFFERSIZE; 
htmlbff = malloc(htmlbff_size); 

if (htmlbff) 
{ 
    while((c = recv(sock, databff, MAXDATASIZE, 0)) > 0) 
    { 
     if (c + q > htmlbff_size) 
     { 
      htmlbff_size *= 2; /* Arbitrary doubling of size. */ 
      char* tmp = realloc(htmlbff, htmlbff_size); 
      if (tmp) 
      { 
       htmlbff = tmp; 
      } 
      else 
      { 
       /* memory allocation failure. */ 
       free(htmlbff); 
       htmlbff = 0; 
       break; 
      } 
     } 
     memcpy(htmlbff + q, databff, c); 
     q += c; 
    } 
} 
+0

Molto bello, grazie, ed è esattamente come sto gestendo la mia memoria, tranne che ho aggiunto un altro passaggio per ridisegnare la dimensione del buffer esattamente a quanti byte ho bisogno al termine del ciclo. Grazie ancora per la risposta. –

1

è necessario mantenere una ridistribuzione/espandere il buffer per adattarsi a tutti i dati (se i dati letti fuori supera presa MAXDATASIZE) = Così come recv legge i dati nella databff, il tuo htmlbff può crescere in memoria e quindi la nuova lettura può essere aggiunta al tuo htmlbff generale.

q e c sono come cursori per tenere traccia di dove sei e quanto lontano devi andare.

memcpy(htmlbff+q, databff, c); //Do this in your whle loop to append the data 
2

Quello che vorrei fare è recv() dati direttamente in htmlbff, a meno che non si deve fare di più l'elaborazione su di esso.

Assicurarsi che si realloc()htmlbff quando i - q è inferiore a MAXDATASIZE modo che ci sia sempre spazio per un altro recv().

Quindi chiamereste recv(sock, htmlbff + q, MAXDATASIZE, 0)