下面是用于QoS数据的FC字段的位格式:
00|01|0001 01000010前2位代表版本,下一位代表2位类型,下一位代表4位子类型,使用ToDS=0、FromDS=1、bit=1。
那么,上述数据通过空中接口发送的顺序是什么呢?(即从左到右或从右到左)
我看到wireshark将数据捕获为“8842”(在最后一个段中,它显示原始数据包数据)。
但是,如果我编写以下代码来打印FC字段数据:
struct mgmt_header_t {
u_int16_t fc; /* 2 bytes */
u_int16_t duration; /* 2 bytes */
u_int8_t addr1[6]; /* 6 bytes */
u_int8_t addr2[6]; /* 6 bytes */
u_int8_t addr3[6]; /* 6 bytes */
u_int16_t seq_ctrl; /* 2 bytes */
};
void my_callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
int radiotapheader_length = (unsigned short int)(*(packet+2));
struct mgmt_header_t *mac_header = (struct mgmt_header_t *) (packet+radiotapheader_length);
printf("FC = %X\n", mac_header->fc);
}产出如下:
FC = 4288我的第二个问题是,它不应该打印8842而不是4288吗?
更新:,我正在更新这个问题,以便更清楚地了解我的疑问所在。
比方说,我想发送一个FC字段为以下格式的QoS数据包:
00|01|0001 01000010所以,我应该写:
mac_header->fc = 0x1142 /* value if read from left to right */或
mac_header->fc = 0x4211或
mac_header->fc = 0x4288 /* value if read from right to left */或
mac_header->fc = 0x8842我的是一台小小的安迪安机器。
发布于 2012-07-19 18:31:36
IEEE 802.11标准(不幸的是,IEEE Get程序目前无法提供该标准)说:
MAC子层中的MPDU或帧被描述为按特定顺序排列的字段序列。第7条中的每个数字描述了在MAC帧中出现的字段/子字段以及它们从左到右传递到物理层收敛过程(PLCP)的顺序。 在图中,字段中的所有位都被编号,从0到k,其中字段的长度为k+1位。一个字段内的八位元边界可以通过获取场模8的位数来获得。数值字段中大于一个八位元的八位元按重要性的递增顺序表示,从最低编号位到最高编号位。字段中大于单个八进制的八位元被发送到PLCP,以便从包含最低编号位的八位位发送到包含最高编号位的八位位组。
因此,发送到PLCP的框架控制字段的第一个八进制是包含B0的八进制,即包含协议版本、类型和子类型字段的八进制。然后是包含DS的八进制,从DS,更多Frag,等等。因此,00|01|0001八进制是传送的第一个八进制。这就变成了内存中一个字节的10001000,从高阶位到低阶位,而不是低阶位到高阶位,因此0x88。下一个八进制是01000010,因此是0x42。
因此,这将以00010001和01000010的形式传递,并将以0x88和0x42的形式出现在内存中。(顺便说一句,这意味着FC字段,就像802.11中的所有其他多八进制积分字段一样,是以小字节顺序传输的,而不是按大端字节顺序传输的。“网络字节顺序”是大端字节顺序;并非所有通过网络传输的数据都是“网络字节顺序”--因特网协议标准中的字段(如IPv4、IPv6、TCP和UDP )都是“网络字节顺序”,但其他协议,包括一些传输IP的协议和一些通过TCP或UDP传输的协议,可以使用小字节顺序)。
就像一个小终端机器接收到的,作为一个16位积分量,在一个小终端机器上是0x4288,有一个多个八进制的积分量,在内存中的第一个八进制是这个量的低阶八进制。因此,您的代码将其打印为0x4288在您的小终端计算机上;如果它运行在一台大端计算机上,它将将其打印为0x8842。
将它打印为0x4288是打印它的“正确”方法,因为它是“在电线上”(或者更确切地说,“在空中”,因为这是802.11 :-))。Wireshark将您的数据包的Frame字段显示为"packet“窗格中的0x4288 (默认情况下是中间窗格);它在”十六进制转储“窗格(默认情况下是底部窗格)中显示为8842,因为它只是按照每个八进制在内存中出现的顺序显示它们。
如果您希望在大端机器和小终端机器上将其打印为0x4288,则需要将其从小端字节顺序转换为主机字节顺序。最简单的方法是使用诸如Wireshark的pletohs()宏这样的工具:
#define pletohs(p) ((unsigned short) \
((unsigned short)*((const unsigned char *)(p)+1)<<8| \
(unsigned short)*((const unsigned char *)(p)+0)<<0))做一些事情,比如
printf("FC = %X\n", pletohs(&mac_header->fc));至于传递该值,无论机器的字节顺序如何,最简单的方法是使用来自Wireshark的phtoles()宏:
#define phtoles(p, v) \
{ \
(p)[0] = (unsigned char)((v) >> 0); \
(p)[1] = (unsigned char)((v) >> 8); \
}并这样做
pletohs(&mac_header->fc, 0x4288);设置mac_header->fc。
发布于 2012-07-19 14:07:04
这是一个字节排序错误。除非您知道您的平台与数据包的内容具有相同的字节顺序,否则不能执行(unsigned short int)(*(packet+2))。在您的例子中,它们是不同的,这就是您看到字节交换位置的原因。
有关字节顺序的更多信息,请参见这篇维基百科文章,也称为endianness。
发布于 2012-07-19 14:20:40
FC被打印为4288,因为您的系统使用很少的endian格式将数据存储在内存中。由于网络通信采用大端格式。
确保使用以下程序
#include <stdio.h>
int main()
{
int a = 0x12345678, j = 0;
char *b =(char*)&a;
printf("\n0x");
for(j=0; j < sizeof(int); j++)
printf("%x", *b++);
printf("\n");
return 0;
}如果打印0x78563412,那么您的机器就是小endian。否则,如果它打印0x12345678,那么它就是大端。
编辑:
我希望后续链接将是有帮助的。
1. http://www.cs.odu.edu/~cs476/fall03/lectures/sockets.htm
2.http://www.ccplusplus.com/2011/10/htons-example-in-c.html
https://stackoverflow.com/questions/11562036
复制相似问题