关于 htonl 和 ntohl 的实现
因为需要直接处理一个网络字节序的 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 {unsigned int ber32;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 时间,但是,明显可读性要高一些。
关于 htonl 和 ntohl 的实现相关推荐
- 【VS开发】IP地址格式转换(htonl、ntohl;inet_addr、inet_ntoa)
1.htonl ()和ntohl( ) u_long PASCAL FAR ntohl (u_long netlong); u_short PASCAL FAR ntohs (u_short nets ...
- 【网络】IP地址格式转换(htonl、ntohl;inet_addr、inet_ntoa)
1.htonl ()和ntohl( ) u_long PASCAL FAR ntohl (u_long netlong); u_short PASCAL FAR ntohs (u_short nets ...
- Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa)
Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa) htonl() htons() ntohl() ntohs()及inet_n ...
- htonl,htons,ntohl,ntohs的详解
大小端模式 对于多字节的数值在系统中如何存储取决于各CPU的实现,而高字节部分是存在低地址还是高地址就有不一样的结果了,因此才有大小端两种模式的存在,而命名则是根据起始地址存放的是数值字节的低处还是高 ...
- htons(), htonl(), ntohs(), ntohl()
在网络编程中,往往会遇到字节的网络顺序和主机顺序的问题. 我们先来了解下字节的网络顺序和主机顺序: 网络字节序与主机字节序 主机字节序:就是我们平常说的大端和小端模式,不同的CPU有不同的字节序类型, ...
- 模拟htonl、ntohl、htons、ntohs函数实现
模拟htonl.ntohl.htons.ntohs函数实现 2010-04-14 17:25:06| 分类: 网络编程 | 标签: |字号大中小 订阅 From: http://wxxweb.bl ...
- 主机字节序与网络字节序的转换函数:htonl、ntohl、htons、ntohs
Part 1: htons函数具体解释 在Linux和Windows网络编程时需要用到htons和htonl函数,用来将主机字节顺序转换为网络字节顺序. 在Intel机器下,执行以下程序 i ...
- htonl函数 c语言,c – 理解htonl()和ntohl()
我试图使用unix套接字测试发送一些udp数据包到localhost. 我的理解是,当设置ip地址和端口以便发送数据包时,我会将我的sockaddr_inwith填充为转换为网络字节顺序的值. 我在O ...
- 记录一次htonl和ntohl的使用方法和差别
实例: 在研究这两个函数时,总是遇到htonl和ntohl输出的值是一样的情况,明明一个是主机序转网络序,一个是网络序转主机序,为什么值会输出一样呢?请看代码: uint32_t ulTemp = 1 ...
- 通俗易懂说字节序,大小端,网络序和主机序(2)htonl和ntohl 源码实现
通俗易懂说字节序,大小端,网络序和主机序(2)htonl和ntohl 源码实现 1. htonl 内核源码实现 1.1 注意:这里有判断,如果本身内存中存储的就是网络序,那就不转 1.1 __bswa ...
最新文章
- pads最新版本是多少_电路EDA软件究竟有多少?
- Fiddler抓取手机APP数据包
- Xcode生成的可执行文件在哪里
- android uinput 按键_android 使用uinput模拟输入设备的方法
- opc服务器状态红叉,西门子S7-300与上位机通过OPC服务器的通讯设置分解.pdf
- shell mysql eof_shell EOF
- label居中_表格固定列宽时如何居中?
- 《构建之法》第8,9,10章
- ROS queue_size和buff_size设置
- java声明代码是什么_java安全编码指南之:声明和初始化说明
- 企业私有云之rabbitmq高可用
- 简单使用apipost和jmeter 测试接口
- iOS申请真机调试证书 图文详解
- 【学习笔记】python实现图像的手绘效果
- w ndows默认截图工具,windows截图工具快捷键
- 淘宝卖家过劳死VS跳楼死
- 07、Flutter FFI 数组
- 涂抹果酱【状压DP】
- 高仿QQ源码 界面(3)
- 沃达丰高管:澳大利亚将于2020年迎来5G