64位主机字节序与网络字节序之间的转换

64位主机字节序与网络字节序之间的转换

  • C字节序转换
  • 64位主机字节序与网络字节序转换

C字节序转换

常用的函数有

函数 功能
ntohs 将一个无符号短整形数从网络字节顺序转换为主机字节顺序。
htons 将无符号短整型主机字节序转换为网络字节序
ntohl 将一个无符号长整形数从网络字节顺序转换为主机字节顺序。
htonl 将无符号长整型网络字节序转换为主机字节序

以上函数对应的是 16 位、 32 位长的数据。

64位主机字节序与网络字节序转换

这个需求没有标准的函数实现,需要手动实现一个。

分析一下,一个 64 位的 long long 型数据,它在主机字节序是怎么存储的:

long long a = 0X123456789abcdef0

在内存中它的存储应该是(小端的话)

f0    de   bc   9a   78    56   34   12
//内存由低到高的增长顺序

那转成大端,应该是:

12    34   56   78   9a    bc   de   f0
//内存由低到高的增长顺序。

当然是需要借助 ntohl htonl 这两个函数来实现,可以把 long long 拆成两个 int 型的数(high 和 low)。

比如 0X123456789abcdef0,就可以拆成 high: 0X12345678,low:0X9abcdef0。

得到的结果应该是:0Xf0debc9a78563412,这个 64 位数也可以拆成 high 和 low;high:0Xf0debc9a,low:0X78563412。

可以发现:
网络序的 high 是 主机序的 low 转网络序
网络序的 low 是主机序的 high 转网络序

就可以写出以下代码:

#define __int64 long long

__int64 ntoh64(const __int64 val )
{
    long high, low;
    low = (long)(val & 0x00000000FFFFFFFF);
    high = val >> 32;
    high = (long)(high & 0x00000000FFFFFFFF);
    low = ntohl( low );
    high = ntohl( high );

    __int64 nRet = 0;
    nRet = low;
    nRet <<= 32;
    nRet |= high;
    return nRet;
}

不过这个代码只适用用主机序为小端字节序的,如果主机序本身就是大端的话,与网络序一样,是不用修改的。再完善一下代码。

#define __int64 long long

int isBigEndian()
{
    union
    {
        short s;
        char c[sizeof(short)];
    } un;
    un.s = 0x0102;
    if(sizeof(short) == 2)
    {
        if(un.c[0] == 1 && un.c[1] == 2)
        {
            return 1;
        }
        else if (un.c[0] == 2 && un.c[1] == 1)
        {
            return 0;
        }
        else
        {
            printf("unknown\n");
            return 0;
        }
    }
    else
    {
        printf("sizeof(short)= %d\n",sizeof(short));
        return 0;
    }
    return 0;
}

__int64 ntoh64(const __int64 val )
{
    int ret = isBigEndian();
    if(1 == ret)
    {
        return val;
    }
    long high, low;
    low = (long)(val & 0x00000000FFFFFFFF);
    high = val >> 32;
    high = (long)(high & 0x00000000FFFFFFFF);
    low = ntohl( low );
    high = ntohl( high );

    __int64 nRet = 0;
    nRet = low;
    nRet <<= 32;
    nRet |= high;
    return nRet;
}

同理 hton64 可以与 ntoh64 一样写法。这里就不赘述了。

你可能感兴趣的:(C)