Article View: borland.public.cppbuilder.internet.socket
Article #2894Re: TWinSocketStream Read in BYTE buffer
From: Maurice Anderson
Date: Thu, 05 Jan 2006 10:04
Date: Thu, 05 Jan 2006 10:04
154 lines
6552 bytes
6552 bytes
Also found an issue in ReadBuf which causes TFileStream *FS to write fewer
bytes to the file than what is in the stream. For example:
(1) We have a file that is hdrfx1.jpg(63,820) bytes sent from the client
http://www.sonystyle.com/intershoproot/eCS/Store/en/imagesProducts/650x650/H
DRFX1.jpg
(2) When it hits my server it first goes to ReadPacket(..)
where it is determined to be a file.
(3) From there it gets sent to ReadFile(..).
(4) ReadFile calls Readbuf in a while loop to read the contents
from the stream into a buffer 256 bytes at a time
TFileStream *FS = new TFileStream(fn, fmCreate);
.....
BYTE rbuf[256];
.....
while( size > 0 )
{
bufsize = size;
if( bufsize > sizeof(rbuf) )
bufsize = sizeof(rbuf);
if( !ReadBuf(rbuf, bufsize) )
{
error = true;
break;
}
if( FS->Write(rbuf, bufsize) < 1 )
{
(5) So ReadBuf is called 249 times to read 63,744 Bytes.
And each time ReadBuf returns, FS faithfully writes the contents
to itself the same 249 times. This leaves the last 76 Bytes to go.
(6) All is good so far until we have to read the last 76 Bytes
to complete the file. For this we have to take a look
at ReadBuf.
bool __fastcall ReadBuf(TWinSocketStream *Stream, void *Buffer, int
BufSize)
{
BYTE *pBuf = (BYTE*) Buffer;
int NumRead;
while( BufSize > 0 )
{
NumRead = Stream->Read(pBuf, BufSize);
if( NumRead < 1 )
return false;
pBuf += NumRead;
BufSize -= NumRead;
}
return true;
}
(7) You see, once the Stream reads those 76 Bytes into pBuf, it cycles
back once more. On this last cycle in encounters 0 bytes to read
so it kicks back a false as the return variable:
if( NumRead < 1 )
return false;
(8) The false return goes back to ReadFile where it gets completely kicked
out of the while loop before those last 76 Bytes are read by FS.
if( !ReadBuf(rbuf, bufsize) )
{
error = true;
break; < - exists loop with 76 bytes
left in rBuf
}
if( FS->Write(rbuf, bufsize) < 1 ) <- Never sees
the last 76 bytes
{
(9) So we end up with a file written short those 76 Bytes.
(10) To resolve this I change around ReadBuf to return the number of
bytes read. If the bytes read from ReadBuf are < 1, then I kick
out
of the while loop.
Therefore, FS gets to read those last 76 Bytes before the while
loop
is exited and we have our complete file transferred.
int __fastcall TBinaryTransfer::ReadBuf(TStream *Stream, void *Buffer,
int BufSize)
{
BYTE *pBuf = (BYTE*) Buffer;
int NumRead;
int NumRead2 = 0;
try
{
while( BufSize > 0 )
{
NumRead = Stream->Read(pBuf, BufSize);
if( NumRead < 1 ){
return NumRead2;
}
NumRead2 = NumRead; <- Holds the last byte amount read
in case we have
to return when we hit zero.
pBuf += NumRead;
BufSize -= NumRead;
}
}
catch(const Exception &)
{
return 0;
}
return 256;
}
ReadFile:
while( size > 0 )
{
if( bufsize > sizeof(rbuf) )
bufsize = sizeof(rbuf);
numread = ReadBuf(Stream, rbuf, bufsize, 0);
if( numread < 1 )
{
error = true;
break; <-- exits only when we
are sure there
is nothing
left in rbuf
}
if( FS->Write(rbuf, numread) < 1 )
{
error = true;
break;
}
size -= bufsize;
}
Thanks again, you are a life saver.......... troubleshooting the code help
me really understood how you read and processed the contents of the stream.
You are truly very talented in this area and a blessing to many people. And
your insights are always appreciated.
-M-
Technical Details
Message-ID:
<43bcedb2$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!news-out.newsfeeds.com!propagator2-sterling.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mailReferences:
<43ac3d34$1@newsgroups.borland.com> <43ac6028$1@newsgroups.borland.com> <43acc4c5$1@newsgroups.borland.com> <43ae5b51$1@newsgroups.borland.com> <43aeebe1$1@newsgroups.borland.com> <43aef70e$1@newsgroups.borland.com> <43af06d7$1@newsgroups.borland.com> <43b252fa$1@newsgroups.borland.com> <43b43a5a$1@newsgroups.borland.com> <43b45550$1@newsgroups.borland.com> <43b5a868$1@newsgroups.borland.com> <43b9b1b0$2@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,74cdc31c66b3abd9 X-Google-Attributes: gid11508e,public X-Google-Language: ENGLISH,ASCII-7-bit From: "Maurice Anderson" <mauriceanderson@hotmail.com> Newsgroups: borland.public.cppbuilder.internet.socket References: <43ac3d34$1@newsgroups.borland.com> <43ac6028$1@newsgroups.borland.com> <43acc4c5$1@newsgroups.borland.com> <43ae5b51$1@newsgroups.borland.com> <43aeebe1$1@newsgroups.borland.com> <43aef70e$1@newsgroups.borland.com> <43af06d7$1@newsgroups.borland.com> <43b252fa$1@newsgroups.borland.com> <43b43a5a$1@newsgroups.borland.com> <43b45550$1@newsgroups.borland.com> <43b5a868$1@newsgroups.borland.com> <43b9b1b0$2@newsgroups.borland.com> Subject: Re: TWinSocketStream Read in BYTE buffer Date: Thu, 5 Jan 2006 02:04:53 -0800 Lines: 156 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1106 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 NNTP-Posting-Host: 64.30.203.223 Message-ID: <43bcedb2$1@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1136455090 64.30.203.223 (5 Jan 2006 01:58:10 -0700) Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news3.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!news-out.newsfeeds.com!propagator2-sterling.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mail