I got a server that is managing two clients through NetworkStream.Read
.
Application protocol is:
ClientMessage [128 Bytes] → Response from Server [128 Bytes]
Now at server-side: Is it possible, that MyTcpClient.GetStream().Read()
returns only < 128 Bytes, although all messages from client-side are exactly 128 bytes long?
I guess that such a client message is short enough to fit into one packet on the tcp/ip layer - but could there be some kind of fragmentation or random although?
Is NetworkStream.DataAvailable
the right attribute to defend against this?
After running smoothly for hours, i sometimes get strange errors and connection losses, that point to something like that.
Thanks in advance.
Is it possible, that MyTcpClient.GetStream().Read() returns only < 128 Bytes
Yes. You can't assume your call to Read( ) will return 128 bytes.
see the docs:
The total number of bytes read into
the buffer. This can be less than the
number of bytes requested if that many
bytes are not currently available, or
zero (0) if the end of the stream has
been reached.
See this link on how to properly read from streams
Try something like this instead: (pass in a 128 length byte array)
private static void ReadWholeArray (Stream stream, byte[] data)
{
int offset=0;
int remaining = data.Length;
while (remaining > 0)
{
int read = stream.Read(data, offset, remaining);
if (read <= 0)
throw new EndOfStreamException
(String.Format("End of stream reached with {0} bytes left to read", remaining));
remaining -= read;
offset += read;
}
}
Short answer:
There is absolutely no guarantee that you will receive the whole packet in one Read
call, even if the packet was sent in one Write
call, and it is smaller than the network MTU, and even if you are in fact sending to/reading from the loopback interface. You cannot do anything about this behavior.
The documentation for Read
clearly states:
An implementation is free to return
fewer bytes than requested even if the
end of the stream has not been
reached.
What you can do would go like this (pseudocode)
While (true) {
Read from stream
If bytes read == 0 {
Socket was closed (buffer should be empty here)
Break
}
Append read data to persistent buffer
While (buffer.Length >= 128) {
Extract first 128 bytes from buffer (buffer length now reduced by 128)
Process message
}
}