关于 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) >> ) | (((x) & 0x00ff0000u) >> ) | \
(((x) & 0x0000ff00u) << ) | (((x) & 0x000000ffu) << ))
如果 CPU 直接支持 bswap32 操作,那这里该用汇编来写? 以提高效率。
网络上是一个个字节传的,而 int 是 32 位,所以,我又定义了这个 union:
union
{
unsigned int ber32;
char mem[];
} 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!"
#endif
sendBuf[bufPos++] = currentData.mem[];
sendBuf[bufPos++] = currentData.mem[];
sendBuf[bufPos++] = currentData.mem[];
sendBuf[bufPos++] = currentData.mem[];
从网络字节序取出数值时候,赋值和 bswap 过程反一下就好。
从网络字节序直接恢复出数值的另一个思路是,既然网络字节序是确定的,那么可以用移位累加的方法直接求出这个 int,如下:
sampleValue = ; 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 的实现的更多相关文章
- 【网络】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)
名词解析: 主机字节序: 不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序.最常见的有两种 1.Little endian:低字节存高地址,高字节存低地址 2.Bi ...
- Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa)
Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa) htonl() htons() ntohl() ntohs()及inet_n ...
- 【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实现
copy #include <IOSTREAM> //#include <WINSOCK.H> using std; typedef uint16; unsigned ...
- htonl(),htons(),ntohl(),ntons()--大小端模式转换函数
不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian). 大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处. 小端模 ...
- ntohs, ntohl, htons,htonl的比较和详解
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题. 这时就可能用到htons(), ntohl(), ntohs(),htons()这4个网络字节顺序与本地字节顺序之间的转换函数 ...
- ntohs, ntohl, htons,htonl对比
ntohs =net to host short int 16位htons=host to net short int 16位ntohl =net to host long int 32位htonl= ...
- 接口处理篇 accept bind connect atan2 htons inet_addr inet_aton inet_ntoa listen ntohl recv send sendto socket
accept(接受socket连线) 相关函数 socket,bind,listen,connect 表头文件 #include<sys/types.h> #include<sys/ ...
随机推荐
- Linux Linux程序练习十四(多进程压力测试)
/* * 题目: * 编程一个基本多进程测试框架,提示用户输入进程数.和每个进程数运行圈数.(fork) * 进行多进程压力测试.(execve) * 要求父进程能监控所有子进程的退出,避免僵尸进程. ...
- http://kb.cnblogs.com/zt/ef/
http://kb.cnblogs.com/zt/ef/ http://blog.csdn.net/mackz/article/details/8605063 http://www.telerik.c ...
- 工作随笔——pre-commit钩子限制日志长度和提交的文件类型
2014-09-18:解决Subversion edge 的hook中文乱码问题 近期检查SVN时发现备份好的文件体积异常庞大.才跑2个月备份出来的大小就有4G多.仔细查询发现很多很多IDE自动生成的 ...
- Oracle 常用操作【01】修改、更新数据
1. oracle 修改表名.列名.字段类型.添加表列.删除表列 alert table scott.test rename to test1--修改表名 alter table scott.tes ...
- JavaEE PO VO BO DTO POJO DAO 整理总结
佩服能将复杂难懂的技术,抽象成简单易懂事物的人. 厌恶将简单易懂的技术,添加一堆专业术语将别人弄的头晕目眩的人. PO VO BO DTO POJO DAO 总体一览: 1.DAO[data acce ...
- bootstrap点滴
1.nav-stacked 这个属性可以决定 tab的变为竖的,不添加的话为横向的. 2.tab 横向的 ul中必须含有nav nav-tabs ul li a 中必须有data-toggle=&q ...
- 数学符号“s.t.”的意义
在优化问题的求解中,如线性规划.非线性规划问题等,经常会遇到数学符号“s.t.”,它的意思是什么呢? “s.t.”,指 subject to,受限制于.... 例如: 目标函数:min {x+2} 约 ...
- Javascript/jQuery 获取地址栏URL参数的方法
1.jquery获取url很简单,代码如下 window.location.href; 2.javascript获取url参数 function getUrlParam(name) { var reg ...
- PagerAdapter 用法
PagerAdapter简介 PagerAdapter是android.support.v4包中的类,它的子类有FragmentPagerAdapter, FragmentStatePagerAdap ...
- JNI系列——C文件中使用logcat
1.在Android.mk文件中添加:LOCAL_LDLIBS += -llog 注:加载的这个库在NDK对应平台目录下的lib目录中. 2.在C文件中添加如下内容: #include <and ...