Dynamic Resizing Of Buffer With ReceiveNetworkData
- the.weavster
- Addict
- Posts: 1576
- Joined: Thu Jul 03, 2003 6:53 pm
- Location: England
Dynamic Resizing Of Buffer With ReceiveNetworkData
As you probably don't know how much data there is before you've received it it would be good if the buffer would just grow to the appropriate size.
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
- the.weavster
- Addict
- Posts: 1576
- Joined: Thu Jul 03, 2003 6:53 pm
- Location: England
Well both REALbasic and Hotbasic can do the impossible.Kaeru Gaman wrote:and it is simply impossible...
*edit*
I think I may have been wrong about Hotbasic.
Last edited by the.weavster on Thu Feb 08, 2007 2:43 pm, edited 2 times in total.
-
- PureBasic Expert
- Posts: 4229
- Joined: Sat Apr 26, 2003 8:27 am
- Location: Strasbourg / France
- Contact:
Well you can do it (yourself) with CopyMemory() and ReAllocateMemory() for example.the.weavster wrote:Well both REALbasic and Hotbasic can do the impossible.Kaeru Gaman wrote:and it is simply impossible...
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
- the.weavster
- Addict
- Posts: 1576
- Joined: Thu Jul 03, 2003 6:53 pm
- Location: England
-
- PureBasic Expert
- Posts: 4229
- Joined: Sat Apr 26, 2003 8:27 am
- Location: Strasbourg / France
- Contact:
Something like this ?the.weavster wrote:I tried doing it with ReallocateMemory() but it kept causing a crash.
Maybe I was doing it wrong, could you give me a code snippet?
Thanks
Weave
Code: Select all
Repeat
If NetworkClientEvent(ConnectionID) = #PB_NetworkEvent_Data
BytesRead = ReceiveNetworkData(ConnectionID, *NetworkDataBuffer, 5000)
If BytesRead > 0
*NewBuffer = ReAllocateMemory(*BigBuffer, TotalBytesRead + BytesRead)
If *NewBuffer
*BigBuffer = *NewBuffer
CopyMemory(*NetworkDataBuffer, *BigBuffer + TotalBytesRead, BytesRead)
TotalBytesRead + BytesRead
; /////////////////////////////////////////
; Test if end of data (depends on protocol)
If EndOfTransmission = #True
Debug "* BREAK (END)"
Break
EndIf
; /////////////////////////////////////////
Else
Debug "* BREAK (ReAllocate failed)"
Break
EndIf
EndIf
EndIf
ForEver
; All the data is in *BigBuffer (length = TotalBytesRead)
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
yes of course, but this will end upgnozal wrote:Well you can do it (yourself) with CopyMemory() and ReAllocateMemory() for example.the.weavster wrote:Well both REALbasic and Hotbasic can do the impossible.Kaeru Gaman wrote:and it is simply impossible...
- either
setting a huge buffer first and shrinkening it after recieve
- or
starting with a small buffer and making it bigger while recieving,
wich will mean recieving really small packages.
both don't sound really advantageous to me...
or did I overlook some serious fact?
afaik network-data does not have a header describing the length of incoming data, have they?
oh... and have a nice day.
- the.weavster
- Addict
- Posts: 1576
- Joined: Thu Jul 03, 2003 6:53 pm
- Location: England
@gnozal
Thank you very much.
Thank you very much.
Which is what you have to do with ReceiveNetworkData() becauseKaeru Gaman wrote:yes of course, but this will end up
- either
setting a huge buffer first
afaik network-data does not have a header describing the length of incoming data
Which is more like I was hoping to achieve.- or
starting with a small buffer and making it bigger while recieving,
wich will mean recieving really small packages.
Adventageous to what? What is your third alternative?both don't sound really advantageous to me...
Yes, why should PureBasic renounce this, while other languages have this feature?the.weavster wrote:Well both REALbasic and Hotbasic can do the impossible.
PB 4.30
Code: Select all
onErrorGoto(?Fred)
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Agreed it can be done, but I must say I don't think your logic will work. This seems more logical to me:
Code: Select all
Repeat
If NetworkClientEvent(ConnectionID) = #PB_NetworkEvent_Data
BytesRead = ReceiveNetworkData(ConnectionID, *NetworkDataBuffer, MaxBytes)
overruns = 0
While BytesRead = MaxBytes ; This means more data to be read
overruns + 1
*result = ReAllocateMemory(*NetworkDataBuffer, MaxBytes + MaxBytes * overruns)
If *result = *NetworkDataBuffer
; successfully enlarged the buffer
; reset the insertion point of the new larger buffer to past the already-read data
BytesRead = ReceiveNetworkData(ConnectionID, *NetworkDataBuffer + (MaxBytes + MaxBytes * (overruns-1)), MaxBytes)
Else
MessageRequester("OOPS!", "Insufficient memory to complete communication")
Break
EndIf
Wend
EndIf
ForEver
BERESHEIT
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
- Joakim Christiansen
- Addict
- Posts: 2452
- Joined: Wed Dec 22, 2004 4:12 pm
- Location: Norway
- Contact:
Sometimes I've noticed that BytesRead can actually be smaller than MaxBytes but still there is more data to be received! It's kinda weird/insane that the help file doesn't warn anyone about this. I found out that I have to include the packet size in a header and never stop reading until I got it all.netmaestro wrote:Code: Select all
BytesRead = ReceiveNetworkData(ConnectionID, *NetworkDataBuffer, MaxBytes) While BytesRead = MaxBytes ; This means more data to be read ... Wend

Edit:
Probably ReceiveNetworkData is a wrapper for recv()?
Code: Select all
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while( iResult > 0 );
Last edited by Joakim Christiansen on Tue Mar 11, 2008 1:38 am, edited 1 time in total.
I like logic, hence I dislike humans but love computers.
- Joakim Christiansen
- Addict
- Posts: 2452
- Joined: Wed Dec 22, 2004 4:12 pm
- Location: Norway
- Contact:
lol
I send 98688 bytes of data and use this function to receive it just to test:
And it outputs this:
But sometimes it actually manage to receive it all in one buffer, the buffer is at 100000 bytes.
Next test:
Changing code to this (as manual suggests):
And setting the buffer to 1000 bytes seems to help maybe, but still it will often end in unfinished transfer:
Conclusion:
What I need to do is to rewrite the ReceiveNetworkData function...
And in these tests the SendNetworkData ALWAYS returned 98688 bytes sent, so it was NOT the problem.
Sometimes the buffer is not filled to the top: (now 2000 bytes)

I send 98688 bytes of data and use this function to receive it just to test:
Code: Select all
Repeat
DataLength = ReceiveNetworkData(ServerID,*Buffer,BufferLength)
TotalSize + DataLength
Debug "recieving..."+Str(TotalSize)+" "+Str(DataLength)
Until DataLength = 0
Debug "done"
As you can see it never debugged "done", which means there is no way for me too see when it has received all the data. This code just hangs after it received the data.recieving...7504 7504
recieving...18760 11256
recieving...22512 3752
recieving...37520 15008
recieving...45024 7504
recieving...48776 3752
recieving...52528 3752
recieving...56280 3752
recieving...60032 3752
recieving...63784 3752
recieving...67536 3752
recieving...71288 3752
recieving...75040 3752
recieving...78792 3752
recieving...82544 3752
recieving...86296 3752
recieving...90048 3752
recieving...93800 3752
recieving...98688 4888
But sometimes it actually manage to receive it all in one buffer, the buffer is at 100000 bytes.
Next test:
Changing code to this (as manual suggests):
Code: Select all
Until DataLength <> BufferLength
(should be 98688)...
recieving...27000 1000
recieving...28000 1000
recieving...29000 1000
recieving...30000 1000
recieving...30660 660
done
Conclusion:
What I need to do is to rewrite the ReceiveNetworkData function...
And in these tests the SendNetworkData ALWAYS returned 98688 bytes sent, so it was NOT the problem.
Sometimes the buffer is not filled to the top: (now 2000 bytes)
What I start to understand is that this is how networks work (it can be unstable) and the help file should let us know.recieving...94000 2000
recieving...96000 2000
recieving...96360 360
recieving...98360 2000
recieving...98688 328
I like logic, hence I dislike humans but love computers.
I forget how much exactly, but internet packets are around 1K. (!)
And obviously even if there IS more data to be received, it can't fill up the buffer fully unless it has received that much data. If a long delay or even temporary timeout or packet loss occur, the socket or api may simply give you what it's got so far.
So you have to keep fetching data until it returns 0.
And if the buffer is 100% full there may still be more data waiting, so again, keep reading until you get 0.
Try to imagine it all as a stream of data not unlike streaming audio or video files.
I don't think the PureBasic team should invest any time in this, it would lead to very bad programming practices, memory bloat and fragmentation.
Putting it into a temporary file, or into a fixed size final destination buffer (if you expect the file to be small and then just abort with an error if you receive way to much for some odd reason) would probably be better for performance.
And obviously even if there IS more data to be received, it can't fill up the buffer fully unless it has received that much data. If a long delay or even temporary timeout or packet loss occur, the socket or api may simply give you what it's got so far.
So you have to keep fetching data until it returns 0.
And if the buffer is 100% full there may still be more data waiting, so again, keep reading until you get 0.
Try to imagine it all as a stream of data not unlike streaming audio or video files.
I don't think the PureBasic team should invest any time in this, it would lead to very bad programming practices, memory bloat and fragmentation.
Putting it into a temporary file, or into a fixed size final destination buffer (if you expect the file to be small and then just abort with an error if you receive way to much for some odd reason) would probably be better for performance.