Discussion:
InternetWriteFile performance question
(too old to reply)
Ziggy
2006-06-21 14:49:55 UTC
Permalink
Ive used InternetWriteFile to make something similar to FtpPutFile, but
with the advantage that, by writting the data by chunks, my app is more
responsive (the ftp code is not in the UI thread, but it helps in other
ways.) Also I have better control of the local file being sent: I read
it all into memory and close any open handles to it, so in case
InternetWriteFile hangs, the local file doesnt get stuck with an open
handle.

My question is, what is the optimal chunk size to send? I want to send
the smallest chunk possible that would not significantly affect banwith
performance (because of each InternetWriteFile overhead, since I have
to call it more times if the chunk is smaller.)

I dont think the sample code is necessary, but here it is anyway:

#define BLOCK //for clarity

BOOL FFTPSendHelper(TCHAR *szFileLocal, TCHAR * szFileFTP)
{
HINTERNET hFileFTP=NULL;
HANDLE hfileLocal = CreateFile(szFileLocal, FILE_READ_DATA,
FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
BYTE *rgFileData = NULL;
if (hfileLocal==INVALID_HANDLE_VALUE)
goto End;
DWORD cbFileTotal=GetFileSize(hfileLocal, NULL);
if (cbFileTotal<=0)
goto End;
try
{
rgFileData = new BYTE[cbFileTotal];
}
catch (...)
{
}
if (rgFileData==NULL)
goto End;
BLOCK //read file into buffer, so we can close the handle asap
{
DWORD cbRead=0;
ReadFile(hfileLocal, rgFileData, cbFileTotal, &cbRead, NULL);
if (cbRead<cbFileTotal)
goto End;
CloseHandle(hfileLocal);
hfileLocal=INVALID_HANDLE_VALUE;
}
BOOL fRet=FALSE;
hFileFTP=FtpOpenFile(g_hFTP, szFileFTP, GENERIC_WRITE,

FTP_TRANSFER_TYPE_BINARY, NULL);
if (hFileFTP==NULL)
goto End;
const int cbChunk=1024; /********** HERE IS THE CHUNK SIZE
*********/
BYTE *pBuffCur=rgFileData;
BYTE * const pBuffMax=rgFileData+cbFileTotal;
do
{
if (g_fStopFTP)
break;
if (pBuffCur>=pBuffMax)
{
fRet=TRUE;
break;
}
DWORD cbWritten = 0;
BYTE *pBuffEnd = min(pBuffCur+cbChunk,pBuffMax);
DWORD cbToWrite=pBuffEnd-pBuffCur;

/********* HERE IS THE WRITE CALL ********/

InternetWriteFile(hFileFTP, pBuffCur, cbToWrite, &cbWritten);

if (cbWritten==0)
break;
pBuffCur+=cbWritten;
}
while (TRUE);

End:
if (hfileLocal!=INVALID_HANDLE_VALUE)
CloseHandle(hfileLocal);

if (hFileFTP)
{
InternetCloseHandle(hFileFTP);
if (!fRet)
FtpDeleteFile(g_hFTP, szFileFTP);
}

if (rgFileData)
delete [] rgFileData;

return fRet;
}
Scherbina Vladimir
2006-06-29 19:49:57 UTC
Permalink
Ziggy,

I don't think you can control the perfomance factor for InternetWriteFile,
because InternetWriteFile may split data into chunks regardless the size of
a chunk you pass to it.

P.S. I suggest you to ask this question in networking ng.
--
Vladimir
Post by Ziggy
Ive used InternetWriteFile to make something similar to FtpPutFile, but
with the advantage that, by writting the data by chunks, my app is more
responsive (the ftp code is not in the UI thread, but it helps in other
ways.) Also I have better control of the local file being sent: I read
it all into memory and close any open handles to it, so in case
InternetWriteFile hangs, the local file doesnt get stuck with an open
handle.
My question is, what is the optimal chunk size to send? I want to send
the smallest chunk possible that would not significantly affect banwith
performance (because of each InternetWriteFile overhead, since I have
to call it more times if the chunk is smaller.)
#define BLOCK //for clarity
BOOL FFTPSendHelper(TCHAR *szFileLocal, TCHAR * szFileFTP)
{
HINTERNET hFileFTP=NULL;
HANDLE hfileLocal = CreateFile(szFileLocal, FILE_READ_DATA,
FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
BYTE *rgFileData = NULL;
if (hfileLocal==INVALID_HANDLE_VALUE)
goto End;
DWORD cbFileTotal=GetFileSize(hfileLocal, NULL);
if (cbFileTotal<=0)
goto End;
try
{
rgFileData = new BYTE[cbFileTotal];
}
catch (...)
{
}
if (rgFileData==NULL)
goto End;
BLOCK //read file into buffer, so we can close the handle asap
{
DWORD cbRead=0;
ReadFile(hfileLocal, rgFileData, cbFileTotal, &cbRead, NULL);
if (cbRead<cbFileTotal)
goto End;
CloseHandle(hfileLocal);
hfileLocal=INVALID_HANDLE_VALUE;
}
BOOL fRet=FALSE;
hFileFTP=FtpOpenFile(g_hFTP, szFileFTP, GENERIC_WRITE,
FTP_TRANSFER_TYPE_BINARY, NULL);
if (hFileFTP==NULL)
goto End;
const int cbChunk=1024; /********** HERE IS THE CHUNK SIZE
*********/
BYTE *pBuffCur=rgFileData;
BYTE * const pBuffMax=rgFileData+cbFileTotal;
do
{
if (g_fStopFTP)
break;
if (pBuffCur>=pBuffMax)
{
fRet=TRUE;
break;
}
DWORD cbWritten = 0;
BYTE *pBuffEnd = min(pBuffCur+cbChunk,pBuffMax);
DWORD cbToWrite=pBuffEnd-pBuffCur;
/********* HERE IS THE WRITE CALL ********/
InternetWriteFile(hFileFTP, pBuffCur, cbToWrite, &cbWritten);
if (cbWritten==0)
break;
pBuffCur+=cbWritten;
}
while (TRUE);
if (hfileLocal!=INVALID_HANDLE_VALUE)
CloseHandle(hfileLocal);
if (hFileFTP)
{
InternetCloseHandle(hFileFTP);
if (!fRet)
FtpDeleteFile(g_hFTP, szFileFTP);
}
if (rgFileData)
delete [] rgFileData;
return fRet;
}
Loading...