在 C 中通过网络套接字发送浮点数的问题

Problems with sending float over network socket in C

我有一个生成范围 [0..10] 内的随机浮点数的客户端。此客户端通过套接字将浮点值发送到服务器,服务器必须显示它。我一直在试图弄清楚如何通过套接字正确发送浮点数,但我无处可去。我设法直接发送了值,但我想做的是将浮点数转换为网络表示并返回,所以我想使用函数 htonl()ntohl() 但我一直没有这样做。我不想在这里复制整个 server/client 代码,因为它有点多,所以我制作了一个小模拟,模拟了发生的事情,它产生了与 server/client 代码中相同的问题。

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char* argv[]) {

    uint32_t tmp, data;
    srand(time(NULL));
    float rand_float = ((float)rand() / (float)RAND_MAX) * 10;
    printf("Generated random float = %f\n", rand_float);

    // client converts to network representation(big endian) and sends the data
    memcpy(&tmp, &rand_float, sizeof(tmp));
    tmp = htonl(tmp);

    // simulate sending the data over the network
    memcpy(&data, &tmp, sizeof(data));

    // server receives the data and has to convert it to host representation (little endian in my case)
    float res = (float) ntohl(data);
    printf("After send: %f\n", res);

    return 0;
}

这与我在 server/client 案例中想要的非常相似。如您所见,客户端将随机浮点数据复制到 uint32_t 变量中,将其转换为网络表示并发送。服务器在 uint32_t 类型的变量 data 中接收该数据,将其转换为主机表示并将该值转换为浮点数。我希望这能奏效。但是当我 运行 这个我得到类似的东西:

Generated random float = 9.266754
After send: 1091847296.000000

或类似的东西。显然这是行不通的。确切的行为发生在我的 server/client 代码中,我得到了类似的输出。同样,在 server/client 代码中,每当我删除与网络表示的转换和 运行 我机器上的服务器和客户端代码时,一切都按预期工作,所以我很确定问题出在某个地方在此转换中,但我没有发现上面的代码有任何问题。我在这里阅读了其他询问此类转换的问题(这就是我发现这种发送浮点数的方法的地方),但它们没有解决我的问题。

float res = (float) ntohl(data);

您必须将这些位重新解释为浮点数,而不仅仅是将整数转换为浮点数。

你可以,例如做:

float res = 0.0;
uint32_t tmp2 = ntohl(data);
memcpy(&res, &tmp2, sizeof(tmp2));

假设您生成浮点数 3.23。它有二进制表示:01000000010011101011100001010010,或1078900818。你做字节交换,你发送它,你再次交换字节。现在你有了原始表示,但你只是做了 (float)1078900818,这就是“1078900818”。仅仅转换是行不通的,因为浮点数是 IEEE-754 编码的。