Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File transfer through sockets, final size with less bytes

I'm trying to receive some file through sockets in C. But the server sends me 64-byte packets for a 1000000 byte file for example and I get approximately 999902 bytes on the destination file.

while ((n = read(sd, buffer_in, BUFSIZE ))) //  BUFSIZE = 64 
{
    if(n<0)
    {
       printf("Fail.\n");
       fclose(archivo);
       return -1;
    }

    if(fwrite(buffer_in, n, 1, f) !=1 ) 
    { 
       printf("fwrite error.\n");
       fclose(archivo);
       return -1;
    }

    bytes+=n;
}

printf("We received %d bytes",  bytes);

When used through a local TCP/IP socket it works, but not in a slow connection. I see through debugging that I get a lot of 64 byte chunks, and a 30 byte chunk near EOF. I know that you can get less bytes on read() since the call returns when any data (>1 byte) is available. But this condition shouldn't be catched by the while? Should return when n == 0, that is no more data (EOF).

Thx for your help.

(EDIT)

Sending code as follows:

while (n=read(file_fd, buffer, BUFSIZE))
{
   write (sdaccept, buffer, n)
}

I know that both read() and write () may return N < BUFSIZE, but shouldn't this loop work out that accordingly? I added up n and returns 1000000, the exact size.

(EDIT II)

Tested with a C source with 10673 bytes, receives 10575 without corruption, except that the destination file LACKS the first 98 bytes!!!

like image 757
Hernán Avatar asked Mar 26 '09 06:03

Hernán


People also ask

How many bytes is a socket?

as you can see write socket the maximum buffer size is 1048576 bytes.

What is write function in socket programming?

Behavior for sockets: The write() function writes data from a buffer on a socket with descriptor fs. The socket must be a connected socket. This call writes up to N bytes of data. Parameter Description fs. The file or socket descriptor.


1 Answers

The sending code provided ignores the fact that write() (or send() ) on a socket is not obliged to write the whole buffer.

write()/send() might decide to write it partially or not write at all if the underlying subsystem refuses to receive more data (for example the network subsystem may have a queue for the data to send and this queue is already full). That's highly likely on a slow connection.

The sending side should check the return value of write() to detect how much data has been actually written and adjust accordingly.

Write should be done somehow like this:

int readAmount;
while( readAmount = read(file_fd, buffer, BUFSIZE) > 0 )
{
    int totalWritten = 0;
    do {
       int actualWritten;
       actualWritten = write (sdaccept, buffer + totalWritten, readAmount - totalWritten);
       if( actualWritten == - 1 ) {
           //some error occured - quit;
       }
       totalWritten += actualWritten;
    } while( totalWritten < readAmount );
}
like image 108
sharptooth Avatar answered Sep 30 '22 00:09

sharptooth