Network Data Bytes Get Truncated?

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.
 
J

Jon Skeet [C# MVP]

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.
 
L

localhost

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 );
 
L

localhost

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...
 
J

Jon Skeet [C# MVP]

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.
 
J

Jeffrey Tan[MSFT]

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top