使用 tcp 将浮点数组从 c++ 发送到 c#

Sending a float array from c++ to c# using tcp

本文关键字:c++ 数组 tcp 使用      更新时间:2023-10-16

我是tcp的新手,并且设置了两个应用程序,一个在C ++中发送数据,另一个在C#中接收数据。我发送两个浮点数组,每个浮点数包含三个浮点数。

数据传输和解包正常,但数据的顺序不一致。例如,我发送 float1、float2、float3,并接收 float2、float1、float3。

我适用的 c++ 是:

float position[3];
float rotation[3];
for (int i = 0; i < 3; i++)
        {
            iResult = send(ConnectSocket, (char*)&position[i], (int) sizeof(float),4);
            iResult = send(ConnectSocket, (char*)&rotation[i], (int) sizeof(float),4);
        }
        if (iResult == SOCKET_ERROR) {
            printf("send failed with error: %dn", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            //return 1;
        }

和 C#:

clientSocket = serverSocket.Accept();
Console.WriteLine("Server: Accept() is OK...");
Console.WriteLine("Server: Accepted connection from: {0}", clientSocket.RemoteEndPoint.ToString());
                            // Receive the request from the client in a loop until the client shuts
                            //    the connection down via a Shutdown.
                            Console.WriteLine("Server: Preparing to receive using Receive()...");
                            while (true)
                            {
                                rc = clientSocket.Receive(receiveBuffer);
                                float transX = System.BitConverter.ToSingle(receiveBuffer, 0);
                                float transY = System.BitConverter.ToSingle(receiveBuffer, 4);
                                float transZ = System.BitConverter.ToSingle(receiveBuffer, 8);
                                float rotX = System.BitConverter.ToSingle(receiveBuffer, 12);
                                float rotY = System.BitConverter.ToSingle(receiveBuffer, 16);
                                float rotZ = System.BitConverter.ToSingle(receiveBuffer, 20);

                                Console.WriteLine(transX + " " + transY + " " + transZ + "n");
                                Console.WriteLine(rotX + " " + rotY + " " + rotZ + "n");
                               // Console.WriteLine("Server: Read {0} bytes", rc);
                                if (rc == 0)
                                    break;
                            }

我在这里的错误是什么?我应该单独发送浮标吗?谢谢。

第一个错误是假设您将收到与您发送的数据完全相同的数据。

不幸的是,当发送多个浮点数时,接收器可能会将它们全部接收(如您所料),但它也可以分几部分接收它们(在假设的最坏情况下,逐字节接收)。

因此,在 while 循环中,例如您可能只接收 10 个字节,但您假设已经接收了 24 个字节。导致很多垃圾。

解决方案:在假设数据存在之前,请与 rc 一起检查您是否收到了正确数量的数据,并以正确管理缓冲区的方式实现循环(即接收第一组数据的结束可能与下一个序列的开始一起)。

还有第二个更微妙的问题:仅当源和目标使用相同的浮点编码时,代码逻辑才有效。 C++标准没有修复这种编码(它通常是IEEE-754,但不一定是,即使它是,不同的字节序可能会影响通过网络发送的字节顺序)。

如果您仅针对 wintel 平台,这可能不是问题。但我认为值得一提的是,如果您的C++部分是针对使用不同架构的物联网设备;-)

编辑:处理缓冲接收的提示

我不精通 C#,但原理是这样的:

    Console.WriteLine("Server: Preparing to receive using Receive()...");
    rc=1; 
    br=0;  // number of bytes in buffer  
    sf=24; // size of one sequence to be received
    while (true)
    {
        while (br<sf && rc>0) { // fill buffer until all bytes of one sequence are there
            rc = clientSocket.Receive(receiveBuffer, br, sf-br,SocketFlags.None);
            br += rc; 
        }             
        if (rc == 0) {
            if (br>0) 
                  Console.WriteLine("Server: interupted while receiving data...");
               break;
        }
        //... here you can convert the content of the buffer 
    }

您发送浮点数的顺序如下所示:

pos1
rot1
pos2
rot2
pos3
rot3

但是,在接收它们时,您将像这样处理数据:

pos1
pos2
pos3
rot1
rot2
rot3

这里的解决方案是从正确的索引读取浮点数。

float transX = System.BitConverter.ToSingle(receiveBuffer, 0);
float transY = System.BitConverter.ToSingle(receiveBuffer, 8);
float transZ = System.BitConverter.ToSingle(receiveBuffer, 16);
float rotX = System.BitConverter.ToSingle(receiveBuffer, 4);
float rotY = System.BitConverter.ToSingle(receiveBuffer, 12);
float rotZ = System.BitConverter.ToSingle(receiveBuffer, 20);