Re: Making sure you receive it all



TCP connection represents a stream. You are not guaranteed
to receive the whole messages that you wrote. You can get
multiple messages in one read, and you can get a portion of
a single message in one read. Because of this fragmentation,
you should not assume that the chunk of data you just read
from the socket is the beginning of a message. Also, you should
not discard any data after the message you processed. TCP
does not drop any data (while the connection is alive), but you
may just do so in your own code at the receiver. Please read
carefully my other reply outlining your basic reading strategy.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@xxxxxxxx
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Daniel" <DanielV@xxxxxxxxxxxxxxxx> wrote in message
news:eVUtGJgNGHA.3360@xxxxxxxxxxxxxxxxxxxxxxx
er?

"Your cardinal error is you assume you get the beginning
of your data packet whenever you receive data on the
socket. "

ok but then you say:

"You can't get data out of order on a TCP connection."

What?

"Alexander Nickolov" <agnickolov@xxxxxxxx> wrote in message
news:OJ1FiZyMGHA.1088@xxxxxxxxxxxxxxxxxxxxxxx
Your cardinal error is you assume you get the beginning
of your data packet whenever you receive data on the
socket. TCP is a streaming protocol and your message
boundaries are not preserved. You need to simply store
all data received in a buffer of your own, then analyze the
stream and split it back into application packets.

You didn't show the source of your GetExpectedSize,
but make sure you both encode at the sender and decode
at the receiver the size in network byte order...

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@xxxxxxxx
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Daniel" <DanielV@xxxxxxxxxxxxxxxx> wrote in message
news:uv0mLfnMGHA.3392@xxxxxxxxxxxxxxxxxxxxxxx
I am quite confused...here is some code with how i was going to implement
it: This is called asynchornously.
As it is called async my _totalStreamSize will continue to be set using
the first 4 bytes f the data so this obviously will not work as the next
bit of data to come through wont have the total size at the front. So
whats the best way?At which point should i store the total?


/// <summary>

/// Callback running Asynchronously firing when data received from the
server

/// </summary>

/// <param name="asyn"></param>

void OnDataReceived( IAsyncResult asyn)

{

CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState ;

try

{

//end receive...

int size = 0 ;

size = theSockId.thisSocket.EndReceive (asyn); //end receive on socket
passed in and return totalbytes read

_totalStreamSize = GetExpectedSize(theSockId.dataBuffer); //returns
total bytes read from first 4 bytes in buffer


if ( size == 0 )

{

theSockId.thisSocket.Close();

}

else

{

lock(this)

{

HandleDataReceived(theSockId.dataBuffer, size);

}

WaitForData();

}

}

catch(SocketException exc)

{

MessageBox.Show(exc.Message,"Failed to receive - " + exc.GetType());

theSockId.thisSocket.Close();

}

catch(Exception exc)

{

MessageBox.Show(exc.Message,"Failed to receive - " + exc.GetType());

theSockId.thisSocket.Close();

}

}


"Alexander Nickolov" <agnickolov@xxxxxxxx> wrote in message
news:OP3YlDmMGHA.3264@xxxxxxxxxxxxxxxxxxxxxxx
Not static of course - a member of your class will be much
better. And you should not reset it to zero, but subtract the
number of bytes used (you may have received more data
which you'll ingore if you reset to zero). Also, shift the remaining
data in your buffer to the beginning and store new data from
that position. Additionally, keep in mind you may get several
messages in one go, so don't stop processing after the first
message, only stop when you encounter an incomplete message.
I'm not familiar with the environment you are using (.NET and
C# would be my first guess), so can't write you sample code.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@xxxxxxxx
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Dan" <dvazanias@xxxxxxx> wrote in message
news:%23mklovkMGHA.3496@xxxxxxxxxxxxxxxxxxxxxxx
Hey

I want to ensure i receive my full data before i process how to
respond but all the tutorials i seen use the Receive() part for the
sockets.

I do whats pasted after this message, this is on the client end.

As you can see i use EndReceive(), and to be honest a little confused
at the difference compared to receive(). I presume my size int will
contain the amount of bytes read on that receive. So before calling my
HandleDataReceived method i would need to do read the first 4 bytes
which contain the length of the total data sent and check does my size
received match that, if not i do not have all the data.

So should i make a static var of totalBytesReceived and when it
matches the expected size by += it to size then do my
handledatareceive() and set my static var back to 0? I presume also
then that i have to keep appending these bytes received onto a byte
array that i will then pass through to my handle function. If so how
do you append bytes? I have ben using memory streams, doing a write
and then when finished doing a getbytes, sound acceptable?

Let me know your opinions? I presume i must do the same server side?

void OnDataReceived( IAsyncResult asyn)

{

CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState ;

try

{

//end receive...

int size = 0 ;

size = theSockId.thisSocket.EndReceive (asyn); //end receive on socket
passed in and return totalbytes


if ( size == 0 )

{

theSockId.thisSocket.Close();

}

else

{

lock(this)

{

HandleDataReceived(theSockId.dataBuffer, size);

}

WaitForData();

}

}

catch(SocketException exc)

{

MessageBox.Show(exc.Message,"Failed to receive - " + exc.GetType());

theSockId.thisSocket.Close();

}

catch(Exception exc)

{

MessageBox.Show(exc.Message,"Failed to receive - " + exc.GetType());

theSockId.thisSocket.Close();

}

}


--
Dan











.



Relevant Pages

  • Re: Repeated read From Socket is Truncated
    ... shutdownOutputto the connection. ... others before you have failed to realize it) is that TCP ... provides a byte stream, not a message stream. ... The receiver keeps reading until N bytes have ...
    (comp.lang.java.programmer)
  • Re: FTP Error 426
    ... TCP also provides a means to communicate to the receiver of data that at some point further along in the data stream than the receiver is currently reading there is urgent data. ... correct description is "command" not "subcommand", specifically an "FTP service command", see section 4.1.3. ...
    (bit.listserv.ibm-main)
  • Re: detect bytes written on abort
    ... makes it unreliable, as a successful fwrite() on a socket may simply mean that the data has been placed in a buffer on the sender, not even passed to the OS yet. ... You don't know that the other end of the TCP connection is on the user's browser. ... to implement a protocol where the sender and receiver always agree ... I only want to be able to track how many bytes were sent to the client, which equals the value that is eventually written to the server log file. ...
    (comp.lang.php)
  • Re: Birth of multi-stream technology ?
    ... >> is part of a stream of packets. ... >> Now that a router can detect that it's passing duplicate streams, ... >> However the sender is sending this same stream to multiple receivers. ... >> When a receiver requests a stream from a sender, ...
    (microsoft.public.win32.programmer.networks)
  • Re: Birth of multi-stream technology ?
    ... >> is part of a stream of packets. ... >> Now that a router can detect that it's passing duplicate streams, ... >> However the sender is sending this same stream to multiple receivers. ... >> When a receiver requests a stream from a sender, ...
    (microsoft.public.win32.programmer.networks)

Loading