tags:

views:

107

answers:

2

http://www.codeproject.com/KB/IP/SocketFileTransfer.aspx?artkw=socket%20send%20a%20file I don't clearly understand this line : // get the file's size first

cbLeftToReceive = sizeof( dataLength );

do
{
    BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
    cbBytesRet = sockClient.Receive( bp, cbLeftToReceive );

    // test for errors and get out if they occurred

    if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
    {
        int iErr = ::GetLastError();
        TRACE( "GetFileFromRemoteSite returned 
          a socket error while getting file length\n"
          "\tNumber of Bytes received (zero means connection was closed) = %d\n"
          "\tGetLastError = %d\n", cbBytesRet, iErr );

        /* you should handle the error here */

        bRet = FALSE;
        goto PreReturnCleanup;
    }

    // good data was retrieved, so accumulate

    // it with already-received data

    cbLeftToReceive -= cbBytesRet;

}
while ( cbLeftToReceive > 0 );

I want to know how get it get size of the file to dataLength :)

This line : BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive; does it right that bp is a byte pointer of dataLength addr but what + sizeof(dataLength) - cbLeftToReceive mean ?

I don't think the file is that small : 4 bytes, just onc Receive how can they receive dataLength and data ? Does it send dataLength first and data after ?

A: 

He/She means that he sets aside the size of int in the start of the buffer, where the size of the file will be placed (it will be later read from the socket)

frag
+2  A: 

Oh. The funny array arithmetic. The idea is to count from the end, so that when you reach the end you know you're done. In pieces:
1. Find the address of dataLength (BYTE*)(&dataLength)
2. Skip to the end of dataLength + sizeof(dataLength)
3. Back up by the number of bytes we expect to receive - cbLeftToReceive
This is where we are writing the bytes we get from the network.

As we get bytes from the network, we reduce cbLeftToReceive (cbLeftToReceive -= cbBytesRet;) and continue trying to receive bytes until we are done. So every time through the loop, bp points to where we need to write the next bytes we Receive().

EDIT:

So now that we know how many bytes we're going to get, how to we receive them without potentially filling all of RAM with hunks of the data? We get a buffer, repeatedly fill it, and flush that buffer to disk whenever it's not empty. When there's still a lot of data (more than a buffer) left to receive, we try to Receive() a fill buffer. When there's less than a full buffer to go, we only request to the end of the file.

  iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? 
                      cbLeftToReceive : RECV_BUFFER_SIZE ;
  iiRecd = sockClient.Receive( recdData, iiGet );

The we catch and handle errors. If there was no error, write however many bytes we got and reduce the number of bytes we expect to receive by the number we got.

  destFile.Write( recdData, iiRecd); // Write it
  cbLeftToReceive -= iiRecd;

If we're still not done receiving bytes, go back to the top and keep going.

  while ( cbLeftToReceive > 0 );

General advice: It's good to practice reading code where you don't pay too much attention to the error handling and exception handling code. Typically what's left is much easier to understand.

Eric Towers
Thanks Eric for great and clear answer but how about the data and dataLength, can you explain it for me ?
nXqd
Amazing answers from u, thanks so much :)
nXqd