2012-08-24 18 views
6

W C miałem działający kod, ale nie mam pojęcia, dlaczego to zadziałało, więc zacząłem go przepisywać, aby zrozumieć, co się dzieje.Jak przechowywać wyjście recv()?

Jak dotąd tak dobrze! Napisałem i jestem w 90% pewien, że rozumiem wszystko, co się teraz dzieje; Problem polega jednak na tym, że nie mam pojęcia, jak zapisać porcję danych odebranych przez recv (databff) do mojego wstępnie przydzielonego bufora (htmlbff).

Rozważmy następujący kod (zauważ, że rozebrałem to trochę w dół, tak że zawiera tylko podstawowe informacje, np nie realokacji pamięci lub wyciek ochronę, itp ...):

#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;   
} 

SO (jeśli Robię to dobrze, a rzeczy idą tak, jak sądzę, że są) c to rozmiar aktualnej porcji danych, a q to całkowita ilość danych otrzymanych do tej pory (q jest zwiększana o c za każdym razem, gdy pętla się powtarza). W tej chwili używam q do obsługi pamięci (na wypadek, gdyby ktoś się zastanawiał), ale wierzę, że będzie to miało również cel w rozwiązaniu tego problemu.

W każdym razie pytanie, które zadaję, dotyczy drugiego komentarza. Jak poprawnie zapisać dane z recv na htmlbff?

Odpowiedz

2

Zastosowanie memcpy i przesunięcie htmlbff przez q:

memcpy(htmlbff + q, databff, c); 

Można podobnie recv bezpośrednio do htmlbff:

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

Ale to dobrze, aby utrzymać oddzielny bufor, i zależnie od pełnego kodu , może sprawić, że sprawy staną się jaśniejsze.

Pamiętaj, że dodasz kontrole przed BUFFERSIZE tak, aby nie kopiować przeszłości granice htmlbff. Wspomniałeś, że usunąłeś obsługę realloc, więc może już to robisz.

stałej nazwy są nieco mylące, gdy buforowanie danych użyłbym BUFFERSIZE wskazać rozmiar każdego fragmencie, to znaczy wielkość databff.

+0

Naprawdę podoba mi się ta odpowiedź, dziękuję. Znalazłem ten najbardziej przydatny, ponieważ mogę teraz po prostu pominąć użycie bufora i napisać bezpośrednio do htmlbff. –

5

Zastosowanie memcpy() skopiować (dołącz) dane do htmlbff ale trzeba także upewnić się, że nie przekraczają wielkości htmlbff. Zatrzymaj odbieranie danych po otrzymaniu bajtów lub użyj realloc(), aby rozszerzyć zakres htmlbff, aby zawierał więcej danych.

Na przykład:

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

Bardzo ładnie, dziękuję, i właśnie tak zarządzam swoją pamięcią, z tym, że dodałem kolejny krok, aby po prostu przesunąć rozmiar bufora dokładnie do ilu bajtów potrzebuję po zakończeniu pętli. Ponownie dziękuję za odpowiedź. –

1

Trzeba zachować realokacji/rozszerza bufor, aby dopasować wszystkie dane (jeśli dane odczytać przekracza gniazdo MAXDATASIZE) = tamtędy jak recv wczytuje dane do databff, twój htmlbff może wzrosnąć w pamięci, a następnie nowy odczyt może być dołączony do twojego ogólnego htmlbff.

q i c są jak kursory, aby śledzić, gdzie jesteś i jak daleko musisz się posunąć.

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

Co zrobiłbym to recv() dane bezpośrednio do htmlbff, chyba że trzeba zrobić więcej przetwarzania na nim.

Upewnij się, że realloc()htmlbff gdy i - q jest mniejsza niż MAXDATASIZE tak, że zawsze jest miejsce dla innego recv().

Następnie należy zadzwonić pod numer recv(sock, htmlbff + q, MAXDATASIZE, 0)