如果从网络中拿到一个以太网数据帧,把这个数据帧。用unsigned char buf数组保存然后逐个字节读取打印(类似 printf (buf[0]、printf (buf[2]、printf (buf[3])),这样是可以不去考虑 高位和低位的。
但是,如果使用了超过 1字节的变量去接受数据,比如 unsigned short 或者 unsigned int,那么就必须考虑高地位,主机字节序列,网络字皆序列。也就是单个字节内的高地位是不存在区别的,
但如果把两个字节拼到一起,正好就是反的。
据个列子
// 下面为从原始数据包中打印TCP数据包头的源端口和目的端口
// 可以从帧格式中看到 34-38正好共4个字节的端口号
//unsigned char raw_package 为原始网路数据包
printf("src port is %.2x%.2x\n",raw_package[34],raw_package[35]);
printf("target port is %.2x%.2x\n",raw_package[36],raw_package[37]);
//打印结果为 src port is 8704 target port is 01bb
// 转为 10进制数字就需要的端口号了。
// 再下面这个错误代码列子,可以表明没有字节序列转化的错误
unsigned short package_double_byte_2[2];
memcpy((void*)package_double_byte_2,raw_package + 34,4);
printf("src port is %0.2x\n",package_double_byte_2[0]));
printf("target port is %0.2x\n",package_double_byte_2[1]));
//打印结果为 src port is 0487 target port is bb01
//可以看到结果与正确的十六进制端口号正好相反。
/*
显然当 使用 memcpy((void*)package_double_byte_2,raw_package + 34,4);
的时候,机器默认给我使用了主机字节序列,
但是从网络中拿到的原始数据包是 网络字节序列
*/
解决方案:
- ntohs,ntohl系列函数。
- 如果还想原生秀操作可以去手动实现高地位转换 (蝶式交换法 参考 https://blog.csdn.net/weixin_34980267/article/details/117014258)