I'm trying to send some data from a C++ server to a C# client. I was able to send over char arrays. But there is some problem with float array.
This is the code on the C++ server side
float* arr;
arr = new float[12];
//array init...
if((bytecount = send(*csock, (const char*)arr, 12*sizeof(float), 0))==SOCKET_ERROR){
}
so yes i'm trying to send over a float array of size 12.
here's the code for the client side. (it was strange that there was no easy way to get the float out of the stream in the first place. I have never used C# before and maybe there's something better?)
//get the data in a char array
streamReader.Read(temp, 0, temp.Length);
//**the problem lies right here in receiving the data itself
//now convert the char array to byte array
for (int i = 0; i < (elems*4); i++) //elems = size of the float array
{
byteArray = BitConverter.GetBytes(temp[i]);
byteMain[i] = byteArray[0];
}
//finally convert it to a float array
for (int i = 0; i < elems; i++)
{
float val = BitConverter.ToSingle(byteMain, i * 4);
myarray[i] = val;
}
let's look at the memory dump on both sides and the problem will be clear -
//c++ bytes corresponding to the first 5 floats in the array
//(2.1 9.9 12.1 94.9 2.1 ...)
66 66 06 40 66 66 1e 41 9a 99 41 41 cd cc bd 42 66 66 06 40
//c# - this is what i get in the byteMain array
66 66 06 40 66 66 1e 41 fd fd 41 41 fd 3d ? 42 66 66 06 40
there are 2 problems here on the c# side- 1) first it does not handle anything above 0x80 (above 127) (incompatible structures?) 2) for some unbelievable reason it drops a byte!!
and this happens in 'temp' right at the time of receiving the data
I've been trying to figure something out but nothing still. Do you have any idea why this might be happening? I'm sure I'm doing something wrong... Suggestions for a better approach?
Thanks a lot
It's not clear from your code what the streamReader
variable points to (ie what's its type?) but I would suggest you use the BinaryReader instead. That way, you can just read data one float at a time and never bother with the byte[]
array at all:
var reader = new BinaryReader(/* put source stream here */)
var myFloat = reader.ReadSingle();
// do stuff with myFloat...
// then you can read another
myFloat = reader.ReadSingle();
// etc.
Different readers do different things with data. For instance the text reader (and stream reader) will assume all is text in a particular encoding (like UTF-8) and may interpret the data in a way you didn't expect. The BinaryReader will not do that as it was designed to let you specify exactly the data types you want to read out of your stream.
I'm not sure about C#, but C++ makes no guarantees about the internal, binary representations of floats (or any other data type). For all you know, 0.42 might be represented using these 4 bytes: '0', '.', '4', '2'.
The easiest solution would be transferring human-readable strings such as "2.1 9.9 12.1 94.9 2.1" and using cin/cout/printf/scanf and friends.
In network, you should always convert your numbers into a common format and then read back. In other terms any data other than bytes should be encapsulated. So regardless of your programming languages, this is what you need to do. I cannot comment on what is wrong with your code but this might solve your issue and will save some headache later on. Think if the architecture is 64 bits or it uses different endian.
EDIT:
I guess your problem lies with signed unsigned and can be solved with Isak's answer, but still mind what I had said.
If you need help on encapsulation check Beej's Network Guide. It should have a sample how to encode floats over network.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With