"McKool" <
XXXX@XXXXX.COM >wrote in message
Quote
i was reading with Socket->ReceiveBuf() but all the data, i mean,
receiving all, using the function Socket->ReceiveLength() and i
was procesing only the first message of that buffer.
Yes, you need to be careful when using ReceiveLength() like that. If
possible, it would be better to prepend each packet with its own header that
specifies the exact size of the packet. Then you always know exactly how
much to read. You also need to be careful with incomplete packets.
ReceiveLength() only tells you how much data is available, but that is no
guarantee that complete packets are available. You may have partial packets
until more data arrives. You should be buffering the socket data and then
processing the buffer when you know you have enough data onhand for
processing complete packets.
Quote
I´m using a Non Blocking connection.
What I described above applies doubly then. The OnRead event is triggered
whenever data is received, even just 1 byte, so you don't know yet whether
you have complete packets or not, so buffering is even more important.
Quote
pTByte Buffer;
Buffer = (pTByte)new TByte[sizeof(TCANMsg)];
Why are you dynamically allocating a fixed size? It would be better to
declare it statically instead:
TByte Buffer[sizeof(TCANMsg)];
Or better yet, just declare a TCANMsg and read into it directly:
TCANMsg Msg;
Socket->ReceiveBuf(&Msg, sizeof(TCANMsg))
Quote
if (Socket->ReceiveBuf((void *)Buffer, sizeof(TCANMsg)) <= 0) {
delete[] Buffer;
return false;
You just corrupted your data stream if ReceiveBuf() returns fewer then a
full TCANMsg. There is no guarantee that when OnRead is triggered,
sizeof(TCANMsg) amount of bytes will actually be available. It is very
possible (and likely) for packets to be split amongst several OnRead event
triggerings. Thus you must buffer your data so that it is still available
the next time the event is triggered so that you can finish any partial
packets packet and then process everything correctly. If you return
prematurely like you are, then you lose your positioning in the socket
stream and you can't guarantee that you will ever be able to read any
packets correctly ever again until you close and reset the socket.
Try this instead:
// create this before you connect the socket,
// and free it after you close the socket
TMemoryStream *DataBuffer = new TMemoryStream;
//...
// see how many bytes are available
int Available = Socket->ReceiveLength();
if( Available>0 )
{
// resize the buffer to store the new bytes
int CurrentSize = DataBuffer->Size;
DataBuffer->Size = (CurrentSize + Available);
// read the new bytes into the buffer, preserving
// any bytes that have not been processed yet
void* ptr = (((BYTE*)(DataBuffer->Memory)) + CurrentSize);
if( Socket->ReceiveBuf(ptr, Available) < Available )
// error ...
// read the buffer until all full packets have been processed
while( (DataBuffer->Position + sizeof(TCANMsg)) <=
DataBuffer->Size )
{
TCANMsg Msg;
DataBuffer->Read(&Msg, sizeof(TCANMsg));
// process Msg as needed.
}
// remove any bytes from memory that have already been processed
// and preserve just the partial packets that are still awaiting
more data
int DataSize = (DataBuffer->Size - DataBuffer->Position);
if( DataSize>0 )
{
MoveMemory(DataBuffer->Memory, ((BYTE*)(DataBuffer->Memory)) +
DataBuffer->Position, DataSize);
DataBuffer->Size = DataSize;
}
else
DataBuffer->Clear();
}
Gambit