File transfer through sockets, final size with les

2019-02-13 14:55发布

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!!!

1条回答
该账号已被封号
2楼-- · 2019-02-13 15:38

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 );
}
查看更多
登录 后发表回答