Search code examples
cwindowssocketsmallocrealloc

recv() on socket by dynamically allocating space


I'm trying to get the source code of my website using c, I'm able to connect and everything but when I implement the recv() code, it only receives the last few bytes of the source code. I'd like to dynamically allocate space for the buffer to receive more using the C functions malloc and realloc.

This is the code I have so far:

char *buffer = NULL;
unsigned int i = 0;
unsigned long LEN = 200;
unsigned long cur_size = 0;

buffer = (char*)malloc(sizeof(char)*LEN);
do
{
    if( status >= LEN )
    {
        cur_size += status;
        buffer = (char*)realloc(buffer, cur_size);
    }
    status = recv(cSocket, buffer, LEN, 0);
    if( status == 0 )
    {
        printf("Bye\n");
    }
    else if( status > 0 )
    {
        printf("%d\n", status);
    }
    else
    {
        printf("socket error=%d\n", WSAGetLastError());
        break;
    }
}while( status > 0 );
printf("%s\n", buffer);

It still doesn't print the whole source code. How should I go about this?

Pseudocode:

buffer = 'len chars';
loop:
if( status >= buffer ) buffer = 'resize to status chars';
status = recv(sock, buffer, len, 0);
end loop

Solution

  • As you resize the buffer in advance this needs to be reflected by its size. Which currently is not the case.

    To fix this you could, for example, initialise cur_size with LEN by changing

    unsigned long cur_size = 0;
    

    to

    unsigned long cur_size = LEN;
    

    Assuming the fix above, you want to append to the buffer and not overwrite it with every call to recv().

    To do so change this line

    status = recv(cSocket, buffer, LEN, 0);
    

    to be

    status = recv(cSocket, buffer + cur_size - LEN, LEN, 0);
    

    A more straight forward approach would be to not track the size of the buffer, but the number of bytes received and just always increase the buffer by a constant size.

    Also the two calls to allocate memory can be replaced by one:

    char *buffer = NULL;
    unsigned long LEN = 200;
    unsigned long bytes_received = 0;
    unsigned long cur_size = 0;
    int status = 0;
    
    do
    {
        if (bytes_received >= cur_size)
        {
            char * tmp;
            cur_size += LEN;
            tmp = realloc(buffer, cur_size);
            if (NULL == tmp)
            {
              fprintf(stderr, "realloc error=%d\n", WSAGetLastError());
              break;
            }
    
            buffer = tmp;
        }
    
        status = recv(cSocket, buffer + bytes_received, LEN, 0);
        if (status == 0)
        {
            printf("Bye\n");
        }
        else if (status > 0)
        {
          bytes_received += status;
          printf("%d\n", status);           
        }
        else /* < 0 */
        {
            fprintf(stderr, "socket error=%d\n", WSAGetLastError());
        }
    } while (status > 0);
    
    printf("%s\n", buffer);