首页 > 解决方案 > 在 C 中通过网络套接字发送浮点数的问题

问题描述

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

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

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

Generated random float = 9.266754
After send: 1091847296.000000

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

标签: csocketsfloating-pointnetwork-programming

解决方案


float res = (float) ntohl(data);

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

你可以这样做:

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

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


推荐阅读