9

我正在用 C 语言进行一些套接字编程,并试图解决字节顺序问题。我的请求(发送)很好,但是当我收到数据时,我的字节都乱了。我从这样的事情开始:

char * aResponse= (char *)malloc(512);
int total = recv(sock, aResponse, 511, 0);

在处理这个响应时,每个 16 位字的字节似乎都颠倒了(我使用的是 UDP)。我试图通过这样做来解决这个问题:

    unsigned short * _netOrder= (unsigned short *)aResponse;
    unsigned short * newhostOrder= (unsigned short *)malloc(total);
    for (i = 0; i < total; ++i)
    {
         newhostOrder[i] = ntohs(_netOrder[i]);
    }

当我将数据视为短数据时,这可以正常工作,但是如果我再次将指针转换为 char,则字节会反转。我究竟做错了什么?

4

6 回答 6

12

好的,您在两个不同级别上所做的事情似乎存在问题。这里的部分混淆似乎源于您对指针的使用,它们指向的对象类型,以及指针指向的内存中值的编码的解释。

内存中多字节实体的编码称为字节序。两种常见的编码称为小端(LE) 和大端(BE)。使用 LE,一个 16 位的量(如 short)首先被编码为最低有效字节 (LSB)。在 BE 下,首先对最高有效字节 (MSB) 进行编码。

按照惯例,网络协议通常将事物编码为我们所说的“网络字节顺序”(NBO),这也恰好与 BE 相同。如果您在大端平台上发送和接收内存缓冲区,那么您将不会遇到转换问题。但是,您的代码将依赖于 BE 约定的平台。如果你想编写在 LE 和 BE 平台上都能正常工作的可移植代码,你不应该假设平台的字节序。

实现字节序可移植性是ntohs()ntohl()htons()htonl()等例程的目的。这些函数/宏是在给定平台上定义的,用于在发送端和接收端进行必要的转换:

  • htons() - 将短值从主机订单转换为网络订单(用于发送)
  • htonl() - 将长值从主机顺序转换为网络顺序(用于发送)
  • ntohs() - 将短值从网络订单转换为主机订单(接收后)
  • ntohl() - 将长值从网络订单转换为主机订单(接收后)

了解您关于在转换回字符时访问内存的评论对内存中实体的实际顺序没有影响。也就是说,如果您以一系列字节的形式访问缓冲区,无论您使用的是 BE 机器还是 LE 机器,您都会以它们实际编码到内存中的任何顺序看到这些字节。因此,如果您在接收后查看 NBO 编码缓冲区,则 MSB 将是第一个 - 总是。如果您在转换回主机顺序后查看输出缓冲区,如果您有 BE 机器,则字节顺序将保持不变。相反,在 LE 机器上,字节现在将在转换后的缓冲区中全部反转。

最后,在您的转换循环中,变量total指的是字节。但是,您正在以shorts. 你的循环保护不应该是total,但应该是:

total / sizeof( unsigned short )

考虑到每个short.

于 2009-02-08T19:11:41.357 回答
3

当我将数据视为短数据时,这可以正常工作,但是如果我再次将指针转换为 char,则字节会反转。

这就是我所期望的。

我究竟做错了什么?

您必须知道发送者发送了什么:知道数据是字节(不需要反转),还是短或长(需要反转)。

Google 获取与 、 和 API 相关ntohshtons教程htons

于 2009-02-08T17:15:02.263 回答
2

目前尚不清楚aResponse代表什么(字符串?结构?)。字节序仅与数值有关,char与 s 无关。您还需要确保在发送方,所有数值都从主机转换为网络字节顺序 ( hton*)。

于 2009-02-08T17:15:52.403 回答
1

除了你原来的问题(我认为已经回答了),你应该看看你的malloc声明。malloc分配字节,无符号短很可能是两个字节。

您的声明应如下所示:

unsigned short *ptr = (unsigned short*) malloc(total * sizeof(unsigned short));
于 2009-02-08T17:18:42.833 回答
0

网络字节顺序是大端,所以如果你想让它有意义,你需要将它转换为小端,但如果它只是一个数组它不应该大惊小怪,发送方如何发送它的数据?

于 2009-02-08T17:09:19.203 回答
0

对于单字节,我们可能不关心字节顺序。

于 2011-06-30T11:59:48.930 回答