views:

45

answers:

2

Hi,

Could anyone direct me as to whether there is a special way of sending images (specifically .jpeg files) across a tcp socket? So far I am developing a webserver that seems to send all the text data well. When it comes to jpeg images, the headers are sent however, the Cygwin console just freezes when it comes to sending the actual data.

The way that I am sending the data is that I first open the file, read the data into a buffer and then push that across. Any suggestions?

    while(!feof(sendFile)){

            bzero(send_buffer,sizeof(send_buffer));
            result = fread (send_buffer,1,sizeof(send_buffer),sendFile);

            while(result>0){
                result = fread (send_buffer,1,sizeof(send_buffer),sendFile);

                if(ferror(sendFile)){
                    printf("Error reading file: %s\n",request_page);
                }
                if((test=send(new_fd,send_buffer,sizeof(send_buffer),0))<0){
                    printf("Send returned %d\n",test);
                    printf("Sending %s Failed\n", request_page);
                    exit(1);
                }
                bzero(send_buffer,sizeof(send_buffer));
            }
        }
        fclose(sendFile);
A: 

There are several things wrong, or potentially wrong, with this code.

result = fread (send_buffer,1,Fsize,sendFile);

This line reads Fsize bytes from sendFile to send_buffer. Now, I don't see here where you get Fsize from, but given it's name, I'm guessing that it's the size of the file. Have you ensured that send_buffer is big enough to hold Fsize bytes? If not, you have yourself a potential buffer overrun here, which can cause random data to be written over your stack, causing all kinds of trouble. You probably mean to read in sizeof(send_buffer). You also seem to have a constant here, MAX_MSG. Is that equal to the size of the send buffer? If not, that line will also have problems. In general, you should try to use one, consistent method of referring to the size of this buffer, so you don't get confused by two different values and cause problems that way.

Next up, you try testing for an error reading the file:

if(result != Fsize && (result!=0)) {
printf("Reading error"); 
exit (1);
}

Now, let's take a look at what the documentation for fread says:

fread() and fwrite() return the number of items successfully read or written (i.e., not the number of characters). If an error occurs, or the end-of-file is reached, the return value is a short item count (or zero).

fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.

Here, you are throwing an error if you don't have exactly Fsize or zero items. Now, according to the docs, you could have either a short count or zero in either an error or an end of file case. To distinguish whether you will need to break out of your loop early, or die because of the error, you will need to call feof and/or ferror.

I would guess that your error lies with the buffer overrun mentioned above, but I'd recommend fixing both of these issues.

Brian Campbell
Hi Brian, Thanks so much for those tips. I fixed those little problems in my code and it has def made a difference - a few pages that I couldnt open before work well. But I'm still having issues with the jpeg images though =s.
BAkz
I have edited my post with the updated code. The send() statement is returning -1 and for the life of me I cant figure out why.. :s
BAkz
The error it gives is: Connection reset by peer. I'm guessing the socket is somehow closing. I've enable the TCP_Keepalive option as well under setsockopt. Still no changes..
BAkz
What HTTP headers are you specifically sending before sending the file data? It makes a big difference in how the receiver reads and interprets the data you are sending.
Remy Lebeau - TeamB
A: 

One major logic flaw you have is that you are calling fread() too many times. You call it once, then just before calling send() you call it again overwritting the previous buffer that you needed to send.

You are also not checking to make sure that send() actually sends the full buffer before you read the next one. And you are sending the entire buffer in full when you should be sending only the number of bytes that fread() actually reads.

Try this instead:

unsigned char send_buffer[...];
bool error = false;

while (!feof(sendFile) && !error)
{ 
    bzero(send_buffer, sizeof(send_buffer)); 

    result = fread(send_buffer, 1, sizeof(send_buffer), sendFile);
    if (result < 1)
    {
        if (ferror(sendFile))
        {
            printf("Error reading file: %s\n", request_page); 
            error = true;
        }
        break;
    } 

    unsigned char *send_buffer_ptr = send_buffer;
    do
    {
        test = send(new_fd, send_buffer_ptr, result, 0);
        if (test <= 0)
        { 
            printf("Send returned %d\n", test); 
            printf("Sending %s Failed\n", request_page); 
            error = true;
            break; 
        } 

        send_buffer_ptr += test;
        result -= test;
    }
    while (result > 0);
}

fclose(sendFile); 

if (error)
    exit(1);
Remy Lebeau - TeamB