Network Data Bytes Get Truncated?

  • Thread starter Thread starter localhost
  • Start date Start date
L

localhost

Network socket client code works correctly:

byte[] nameBytes = new byte[2048];
recvData = inStream.Read( nameBytes , 0 , 1024 );
string fileNameRaw = System.Text.Encoding.UTF8.GetString( nameBytes );
string fileName = fileNameRaw.Substring( 0 ,
fileNameRaw.IndexOf("***") );
Console.WriteLine( fileName );



Network socket server code works correctly:

int fileNameCharLength = fileName.Length + 3 ;
byte[] nameBytes =
System.Text.Encoding.UTF8.GetBytes( fileName + "***" );
networkStream.Write( nameBytes , 0 , fileNameCharLength );
networkStream.Flush();


But if I change the encoding to BigEndianUnicode, it does not work.
How should the encoding change to handle that?

Thanks.
 
localhost said:
Network socket client code works correctly:

byte[] nameBytes = new byte[2048];
recvData = inStream.Read( nameBytes , 0 , 1024 );

No, that *doesn't* work correctly. You're assuming that it's read the
whole 1K of data.

See http://www.pobox.com/~skeet/csharp/readbinary.html

That's probably what's going wrong for you.
string fileNameRaw = System.Text.Encoding.UTF8.GetString( nameBytes );

Here you're also using the whole array, despite the fact that *at most*
1K of it has been populated. You should specify how much of the byte
array to use.
 
I am implementing a minimal-but-custom protocol:
1.Client connects to server socket
2.Client sends size of coming binary-envelope of
parameters
3.Client sends envelope of parameters
4.Server returns size of result
5.Server returns name of result
6.Server returns result

The part I am trying to cover right now is step 5. I
know the name (it's a filename) is not larger than 1024
bytes, so I append "***" to the end, and when the client
gets the data, it strips off the end bytes and now has a
filename it can use.

I checked out the web page you mentioned, and while I
really like the "using" for MemoryStream, I am not clear
why I should use a while loop when I know (or am I just
assuming?) that the data is small. I actually do use a
while for step 6 (the only time I know the data will be
= 1024 bytes).

Feel free to straighten me out. :)

Thanks.


-----Original Message-----
localhost said:
Network socket client code works correctly:

byte[] nameBytes = new byte[2048];
recvData = inStream.Read( nameBytes , 0 , 1024 );

No, that *doesn't* work correctly. You're assuming that it's read the
whole 1K of data.

See http://www.pobox.com/~skeet/csharp/readbinary.html

That's probably what's going wrong for you.
string fileNameRaw =
System.Text.Encoding.UTF8.GetString( nameBytes );
 
I set a breakpoint on the byte-reading area, and with a
test file, I can see that UTF8 encoding is 47 bytes. If
I switch to BigEndianUnicode, then I can see 94 bytes in
the debugger, but still it does not display correctly in
the console app.

Hmmm...
 
localhost said:
I am implementing a minimal-but-custom protocol:
1.Client connects to server socket
2.Client sends size of coming binary-envelope of
parameters
3.Client sends envelope of parameters
4.Server returns size of result
5.Server returns name of result
6.Server returns result

The part I am trying to cover right now is step 5. I
know the name (it's a filename) is not larger than 1024
bytes, so I append "***" to the end, and when the client
gets the data, it strips off the end bytes and now has a
filename it can use.

You've missed the point - it's not the length of the "total" data
that's at issue here, it's that a single call to Read might not return
the whole data. For instance, it could be split over two network
packets and each Read might only give the results of a single packet.

If you know the amount of data you should be reading (which is always a
very, very good idea) you should do something like:

byte[] data = new byte[lengthOfIncomingData];
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;
}

As it is, you could just as easily be "over-reading" (i.e. getting some
of the result itself) in with the name, which is just as problematic.
 
Hi,

Does Jon's reply resolve your problem?
If you still have any concern, please feel free to tell me, I will work
with you.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
Back
Top