receiving a C struct via sockets

M

Mike Margerum

I am sending a C struct from a C app via sockets to a C# server. I
occasionally get an error when reading a C char array using the
BinaryReader Class. the error is:

"The output char buffer is too small to contain the decoded characters"

The code that reads a C string looks like this (br is a binaryreader)
private string ReadString(int maxLen)
{
char[] str = br.ReadChars(maxLen);
int i = 0;
while (str != 0)
i++;
return new string(str, 0, i);
}

I'm pretty sure what is happening here is I have garbage in the end of
the C char array after the 0 NULL terminator and C# is trying to encode
these garbage values.

My question is what is the best way for me to read this 40 bytes in and
converting it to a C# string only to where the NULL(0) byte is in the C
char array?


Thanks!
 
M

Mike Margerum

Would setting the Encoding of the BinaryReader to AsciiEncoding fix this?
 
B

Barry Kelly

Mike said:
I am sending a C struct from a C app via sockets to a C# server. I
occasionally get an error when reading a C char array using the
BinaryReader Class. the error is:

"The output char buffer is too small to contain the decoded characters"

The code that reads a C string looks like this (br is a binaryreader)
private string ReadString(int maxLen)
{
char[] str = br.ReadChars(maxLen);
int i = 0;
while (str != 0)
i++;
return new string(str, 0, i);
}

I'm pretty sure what is happening here is I have garbage in the end of
the C char array after the 0 NULL terminator and C# is trying to encode
these garbage values.


I would write an extension method, or write a descendant of
BinaryReader, that directly read bytes from BaseStream until the 0 byte,
and do the conversion from that; either a simple conversion for ASCII,
or by buffering in a MemoryStream, List<byte> or similar and thence
through an Encoding.

I'd also make sure the BaseStream is a BufferedStream to avoid
performance costs of calling e.g. a NetworkStream looking for single
bytes.

-- Barry
 
M

Mike Margerum

Thanks barry.

If I read the data into a byte array (using BinaryReader.ReadBytes)
instead of a char array would I still have encoding issues?

If not , ill go the route you described below.

Thanks

Barry said:
Mike said:
I am sending a C struct from a C app via sockets to a C# server. I
occasionally get an error when reading a C char array using the
BinaryReader Class. the error is:

"The output char buffer is too small to contain the decoded characters"

The code that reads a C string looks like this (br is a binaryreader)
private string ReadString(int maxLen)
{
char[] str = br.ReadChars(maxLen);
int i = 0;
while (str != 0)
i++;
return new string(str, 0, i);
}

I'm pretty sure what is happening here is I have garbage in the end of
the C char array after the 0 NULL terminator and C# is trying to encode
these garbage values.


I would write an extension method, or write a descendant of
BinaryReader, that directly read bytes from BaseStream until the 0 byte,
and do the conversion from that; either a simple conversion for ASCII,
or by buffering in a MemoryStream, List<byte> or similar and thence
through an Encoding.

I'd also make sure the BaseStream is a BufferedStream to avoid
performance costs of calling e.g. a NetworkStream looking for single
bytes.

-- Barry
 
M

Mike Margerum

Peter said:
I doubt it. But it's so simple for you to check yourself, I'm not sure
why you posted that part of the question here.

It's not happening in my test environment and i'm not going to
experiment on the production server.
Now, as far as the actual situation goes, if your string is variable
length and delimited by a null terminator, then you will have to look

So do you think i can use the ReadBytes BinaryReader to reads the entire
array into a byte buffer and then look for the NULL?


Thanks
 
B

Barry Kelly

Mike said:
Thanks barry.

If I read the data into a byte array (using BinaryReader.ReadBytes)

As long as the C-side is sending out a fixed buffer, that's fine, I'm
sure. I was assuming the worst case: an unknown number of bytes
terminated by null.
instead of a char array would I still have encoding issues?

If not , ill go the route you described below.

Thanks

Barry said:
Mike said:
I am sending a C struct from a C app via sockets to a C# server. I
occasionally get an error when reading a C char array using the
BinaryReader Class. the error is:

"The output char buffer is too small to contain the decoded characters"

The code that reads a C string looks like this (br is a binaryreader)
private string ReadString(int maxLen)
{
char[] str = br.ReadChars(maxLen);
int i = 0;
while (str != 0)
i++;
return new string(str, 0, i);
}

I'm pretty sure what is happening here is I have garbage in the end of
the C char array after the 0 NULL terminator and C# is trying to encode
these garbage values.


I would write an extension method, or write a descendant of
BinaryReader, that directly read bytes from BaseStream until the 0 byte,
and do the conversion from that; either a simple conversion for ASCII,
or by buffering in a MemoryStream, List<byte> or similar and thence
through an Encoding.

I'd also make sure the BaseStream is a BufferedStream to avoid
performance costs of calling e.g. a NetworkStream looking for single
bytes.

-- Barry


-- Barry
 
M

Mike Margerum

All due respect, unless you come up with a repro case on your test
environment, you're _are_ going to test any change that you implement on
the production server.
With all due respect, i've been doing c/c++ development for 18 years and
really don't need advice on testing/deployment methodologies. About
12 of them years involve sockets/middleware development. You have no
idea how I have things setup so kindly stay on topic here.

I can turn this code of on my middleware and revert back to FTP. There
are other platforms this middleware is serving well.

Personally, I would change the code so that you are not using
BinaryReader, and just reading data from the socket straight into a
byte[]. Do all the processing on the data _after_ you get it from the
socket.
I'll look into this. Thanks. Part of the problem is i'm obviously new
to C# and do not have my head wrapped the enormous library.
You can use BinaryReader.ReadBytes() if you want, but it won't return
until it's either read the number of bytes you asked for, or it reaches
the end of the stream. Either way, you are likely to at some point have

I *am* reading a fixed size array. The data will always be 40 bytes.
the string itself is variable in size because of a null pointer.
BinaryReader can be very useful when you know in advance the exact size
of everything you're reading. But I think in this situation, it's
probably counter-productive.

I do know the exact size and this is what is puzzling me. It reads fine
100% of the time for me but I am getting the error from folks in the
field.
 
M

Mike Margerum

As long as the C-side is sending out a fixed buffer, that's fine, I'm
sure. I was assuming the worst case: an unknown number of bytes
terminated by null.

Yes it is fixed size Barry. I think the readBytes is going to work in
this instance. I'll keep you posted.


Thanks so much for the help.
 
M

Mike Margerum

reading the c char array in as a bytes array using binaryRead.ReadBytes
seems to have solved the problem.

Thanks very much for the help
 

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