从C++服务器向C#客户端发送浮点数数组

7

我想在C++服务器和C#客户端之间传输一些数据。我已经成功发送了char数组,但是在发送float数组时遇到了问题。

以下是C++服务器端的代码:

float* arr;
arr = new float[12];
//array init...
if((bytecount = send(*csock, (const char*)arr, 12*sizeof(float), 0))==SOCKET_ERROR){
}

是的,我正在尝试发送一个大小为12的浮点数组。

这是客户端代码。(奇怪的是一开始没有简单的方法从流中获取浮点数。我以前从未使用过C#,也许有更好的方法?)

//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;
}

让我们查看双方的内存转储,问题就会变得清晰明了 -

//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

这里有两个C#方面的问题 - 1)首先,它无法处理0x80(大于127)以上的任何内容(不兼容的结构?) 2)由于某种难以置信的原因,它会掉一个字节!!

而这发生在“temp”接收数据的时候。

我一直在尝试找出解决办法,但还是没有头绪。 您有任何想法吗?我确定我做错了什么... 建议采用更好的方法?

非常感谢

3个回答

5
你的代码并不清楚streamReader变量所指向的对象是什么(即它的类型是什么?),但我建议你使用BinaryReader。这样,你就可以一次读取一个浮点数的数据,而且根本不需要考虑 byte[] 数组: one float at a time
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.

不同的读取器对数据的处理方式是不同的。例如,文本读取器(和流读取器)将假定所有数据都是以特定编码(如UTF-8)的文本,并且可能会以您意想不到的方式解释数据。BinaryReader则不会这样做,因为它被设计成让您指定希望从流中读取的确切数据类型。


StreamReader 被定义为 System.IO.StreamReader(<NetworkStream>)。是的,我认为 BinaryReader 可能是更好的选择。谢谢,让我试一下。 - sg88

2
我不确定 C# 是否会有这个问题,但 C++ 并没有保证浮点数(或任何其他数据类型)的内部二进制表示形式。你无法确定,0.42 可能使用以下 4 个字节来表示:'0','.','4','2'。
最简单的解决方法是传递人类可读的字符串,例如 "2.1 9.9 12.1 94.9 2.1",然后使用 cin/cout/printf/scanf 等函数。

printf 有没有关于输出格式的保证? - svick
理论上我同意,但实际上,除了 IEEE 754(它定义了双精度和单精度浮点数),还有其他不同的浮点数表示方法吗? - Isak Savo
(顺便说一句,C#确实指定了浮点数和双精度数的格式应与上述标准中定义的相同)http://msdn.microsoft.com/en-us/library/aa691146(v=vs.71).aspx - Isak Savo
不过,实现可以自由地使用双精度来表示“float”。我手头没有标准,所以无法检查,但重点是编写可移植程序时必须这样做。字节顺序是另一个需要注意的问题。感谢提到C#。 - aib
是的,尽管必须注意当前的区域设置。 - aib

1
在网络中,你应该始终将你的数字转换成一个通用的格式,然后再读取回来。换句话说,除了字节以外的任何数据都应该被封装起来。所以无论你使用什么编程语言,这就是你需要做的。我无法评论你的代码有什么问题,但这可能会解决你的问题,并且稍后能避免一些麻烦。要考虑体系结构是否为64位或者使用了不同字节序。
编辑:
我猜你的问题可能出在有符号和无符号之间,可以通过Isak的答案来解决,不过还是要注意我之前说的内容。
如果你需要关于封装的帮助,请查阅Beej的网络指南。它应该有一个示例教你如何在网络上编码浮点数。

是的,我知道这个。只是如果你查看内存转储,一些浮点数可以很好地传输! - sg88

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接