Deal with endianness in cross-platform network programming

关于跨平台网络编程中传输数据的字节序问题,Linux中提供了四个函数:

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

这四个函数分别用于16位和32位整型在主机字节序和网络字节序之间的转换。在应用中,比如16位整数,在传输前调用htons转为网络字节序后发送,接收方在收到数据后先调用ntohs转换为接收端的主机字节序。

那么若是要传输浮点数(如32位的float类型),又应该怎么办呢?
维基百科上对于浮点数的字节序有如下一段描述:
“On some machines, while integers are represented in little-endian form, floating point numbers are represented in big-endian form. Because there are many floating point formats, and because there is an absence of a “network” standard representation for them, no endianness standard for transferring floating point values between heterogeneous systems has become universally accepted. This means that floating point data written on one machine may not be readable on another, and this is the case even if both use IEEE 754 floating point arithmetic since the endianness of the memory representation is not part of the IEEE specification.“
在某些机器上,存在整型数据以little-endian形式存储而浮点型数据以big-endian形式存储的情况。对于浮点数来说并不存在一个通用的网络字节序标准。因此若需要传输浮点数,为了保证能够解析,必须自己手动做字节序的处理。


在转换之前,需要先判断本机字节序:

#include <stdint.h>

/*
 * Test host endianness.
 * Returns 0 for little-endian, 1 for big-endian
 */

int test_endian(){
    float f = -1.0;
    uint8_t *fp = (uint8_t *)&f;
    if((int)(*fp)<0)
        return 1;
    else return 0;
}

此处使用浮点数-1.0作为样本来判断字节序。根据IEEE754表示法,-1.0的二进制表示形式(从高位至低位)为

1 01111111 00000000000000000000000

第一位为1,因此高位字节做int型解时必小于零,低位字节必等于零,即可判断字节序。

转换字节序代码如下:

#include <stdint.h>

/*
 * Convert a float number between big-endian and little-endian
 */

void convert_endian(float *f){
    uint8_t *fp = (uint8_t *)f;
    uint8_t temp;

    temp = fp[0];
    fp[0] = fp[3];
    fp[3] = temp;
    temp = fp[1];
    fp[1] = fp[2];
    fp[2] = temp;
}

若设定网络字节序为big-endian,则在发送端发包前或接收端收包后完成字节序的判断和数据转换工作。

    /* f is the float number to send or receive */
    if (test_endian() == 0)
         convert_endian(&f);
If you enjoyed this post, make sure you subscribe to my RSS feed!
  1. 咳 在读高三学生 Linux控 为姐姐才华倾倒- – 希望能交个朋友

  2. 咳 毕业三年老师 Linux控 为妹妹才华倾倒- – 希望能交个朋友。。。哈哈~

    开个玩笑~

    貌似你在开发跨平台的app?

  3. @bash
    你也来欺负我哼_,=
    不是,之前实习的时候做的ARM板子上的开发中碰到的一些问题,跨平台好麻烦> <

  4. 恩~,ARM看样子前景不错阿~,有时间其实挺想玩玩android的。。。可惜总找不到时间。。。

    貌似没有在你的blog里发现 鱼鱼 的身影?~~

    • 我下部手机肯定不买Android了…现在就是堆硬件配置,高配半年就变低配了,坑爹阿!
      小鱼童鞋是没来过….

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>