java ntohl 类似函数_关于 htonl 和 ntohl 的实现

本文介绍了在Java中处理网络字节序的32位整数的方法,包括使用系统函数 htonl 和 ntohl 的原理,以及在不同字节序系统下的实现。通过union类型和位移累加的方式,详细解析了如何从网络字节序转换并发送数据。
摘要由CSDN通过智能技术生成

因为需要直接处理一个网络字节序的 32 位 int,所以,考虑用自己写的还是系统函数效率更高。然后又了下面的了解。

首先是系统函数 htonl ,我在 kernel 源码 netinet/in.h 找到如下定义:

# if __BYTE_ORDER ==__BIG_ENDIAN/*The host byte order is the same as network byte order,

so these functions are all just identity.*/# define ntohl(x) (x)

# define ntohs(x) (x)

# define htonl(x) (x)

# define htons(x) (x)

#else#if __BYTE_ORDER ==__LITTLE_ENDIAN

# define ntohl(x) __bswap_32 (x)

# define ntohs(x) __bswap_16 (x)

# define htonl(x) __bswap_32 (x)

# define htons(x) __bswap_16 (x)

# endif

# endif#endif

可以看到,如果系统是 BIG_ENDIAN 那么网络字节序和运算字节序是一致的,如果是 LITTLE_ENDIAN 那么需要进行 __bswap_32() 操作。__bswap_32() 在 gcc 中实现,位于bits/byteswap.h(不要直接引用此文件;使用 byteswap.h 中的 bswap32 代替):

/*Swap bytes in 32 bit value.*/

#define __bswap_constant_32(x) \((((x)& 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) |\

(((x)& 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))

如果 CPU 直接支持 bswap32 操作,那这里该用汇编来写? 以提高效率。

网络上是一个个字节传的,而 int 是 32 位,所以,我又定义了这个 union:

union

{

unsignedintber32;char mem[4];

} currentData;

这样,就直接把各个 byte 给直接取出来了。

所以,按这个思路,完整的过程就是:

#if BYTE_ORDER == BIG_ENDIAN

#warning "BIG_ENDIAN SYSTEM!"currentData.ber32=sampleValue;#elif BYTE_ORDER == LITTLE_ENDIAN

#warning "LITTLE_ENDIAN SYSTEM!"currentData.ber32=bswap_32(sampleValue);#else

#error "No BYTE_ORDER is defined!"

#endifsendBuf[bufPos++] = currentData.mem[0];

sendBuf[bufPos++] = currentData.mem[1];

sendBuf[bufPos++] = currentData.mem[2];

sendBuf[bufPos++] = currentData.mem[3];

从网络字节序取出数值时候,赋值和 bswap 过程反一下就好。

从网络字节序直接恢复出数值的另一个思路是,既然网络字节序是确定的,那么可以用移位累加的方法直接求出这个 int,如下:

sampleValue = 0;

sampleValue += (buff[posOfSamples + 0] << (8 * 3)) );

sampleValue += (buff[posOfSamples + 1] << (8 * 2)) );

sampleValue += (buff[posOfSamples + 2] << (8 * 1)) );

sampleValue += (buff[posOfSamples + 3] << (8 * 0)) );

虽然后面一个比 bswap 多几个 cpu 时间,但是,明显可读性要高一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值