Keith Miller
Keith Miller

Reputation: 1347

How to store output of recv()?

In C I had working code but have no idea why it worked, so I started rewriting it so I could actually understand what is going on.

So far so good! I rewrote and am 90% sure I understand everything that is going on now; the issue however, is that I have no idea how to store the data chunk received by recv (databff) into my pre-allocated buffer (htmlbff).

Consider the following code (note that I stripped this down quite a bit, so it only includes the basics, e.g. no memory reallocation or leak protection, etc...):

#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 (if I am doing this right, and things are going as I think they are) c is the size of the current data chunk, and q is the total amount of data received so far (q is incremented by c each time the loop repeats). At the moment I am using q for memory handling (in case anybody was wondering) but I believe that it will also have purpose in the solution to this problem.

At any rate the question I am asking is in regards to the second comment. How do I store the data from recv into htmlbff correctly?

Upvotes: 6

Views: 3034

Answers (4)

pb2q
pb2q

Reputation: 59637

Use memcpy, and offset htmlbff by q:

memcpy(htmlbff + q, databff, c);

You can similarly recv directly into htmlbff:

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

But it's fine to keep a separate buffer, and depending upon your full code, it may make things clearer.

Be sure that you add checks against BUFFERSIZE so that you don't copy past the bounds of htmlbff. You mentioned that you've stripped out realloc handling, so maybe you're already handling this.

Your constant names are a bit confusing, when buffering data I would use BUFFERSIZE to indicate the size of each chunk, i.e. the size of databff.

Upvotes: 2

hmjd
hmjd

Reputation: 122001

Use memcpy() to copy (append) data to the htmlbff but you also need to ensure you do not exceed the size of htmlbff. Either stop receving data when BUFFERSIZE bytes have been received or use realloc() to extend htmlbff to contain more data.

For example:

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

Upvotes: 5

Zan Lynx
Zan Lynx

Reputation: 54345

What I would do is recv() data directly into htmlbff, unless you need to do more processing on it.

Make sure that you realloc() htmlbff when i - q is less than MAXDATASIZE so that there is always room for another recv().

Then you would call recv(sock, htmlbff + q, MAXDATASIZE, 0)

Upvotes: 2

ddoor
ddoor

Reputation: 5973

You need to keep reallocating/expanding the buffer to fit all the data (if the data read off the socket exceeds MAXDATASIZE) = That way as recv reads data into the databff, your htmlbff can grow in memory and then the new read can be appended to your overall htmlbff.

q and c are like cursors to keep track of where you are up to and how far you have to go.

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

Upvotes: 1

Related Questions