[Mono-list] Socket code.

George Farris george@gmsys.com
Sun, 22 Feb 2004 17:49:45 -0800


On Mon, 2004-02-23 at 02:21, Jonathan Gilbert wrote:
> >Interesting, this code will work as long as the check at the bottom is
> >1448, any other number and it croaks???  The buffer can be any size
> >presumably larger than 1448 and it will work.
> 
> Note (to original poster) that if you want to read up to the end of the
> stream, you should actually check 'len' against '0':
> 
>   if (len < 0)
>     error_occurred();
>   if (len == 0)
>     end_of_stream_occurred();
> 
> You shouldn't assume that the underlying transport will always be able to
> deliver chunks of the same size. The 1448 here has most likely to do with
> the sending computer's TCP/IP stack. Perhaps it ties the TCP packet size
> into the MTU to decrease fragmentation & increase performance (this is
> fairly common, as I understand). Assuming this is the case, your problem is
> simply evidence that, unlike my 'ReadFully' function,
> 'NetworkStream::Read()' does not try to completely read the requested
> buffer. Instead, it does one read attempt and then immediately returns. So,
> you're limited to the size that 'Socket::Receive()' will give you.
> 
> In short, any positive value from 'Socket::Receive()' indicates that there
> could be additional data waiting; a return value of 0 indicates that the
> connection was shut down in that direction (thus indicating the
> end-of-stream). Simply getting a smaller value than you requested does not
> indicate that the end of the stream has been reached. This is distinctly
> different from file I/O.
> 
Well I do check for len > 0, here is the entire function, I also
understand about the TCP packet size not being consistent but what I
don't understand is why this actually works only like this?  Seems like
a bug in the stream code.
 
private string read (NetworkStream stream, TcpClient c)
{
	int len;
	string s;
	StringBuilder buf = new StringBuilder();
			
	do {
		byte[] bytes = new byte[50000];
		len = stream.Read(bytes, 0, (int)50000);
		if (len > 0 ) {
			s = Encoding.ASCII.GetString(bytes,0,len);
			buf.Append(s);
		}
		if (len < 1448)
			break;
	} while (len > 0);
	
	return buf.ToString(); 
}

If I take the if (len < 1448) out it doesn't work.  If I change the 1448
to something else, it doesn't work. 

-- 
George Farris <george@gmsys.com>