因为需要直接处理一个网络字节序的 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 的实现的更多相关文章

  1. 【网络】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 ...

  2. IP地址格式转换(htonl、ntohl;inet_addr、inet_ntoa)

    名词解析: 主机字节序: 不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序.最常见的有两种 1.Little endian:低字节存高地址,高字节存低地址 2.Bi ...

  3. Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa)

    Socket中常见的几个转换函数(htonl,htons,ntohl,ntohs,inet_addr,inet_ntoa) htonl() htons() ntohl() ntohs()及inet_n ...

  4. 【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 ...

  5. IP地址转换、主机大小端、htonl、ntohl实现

    copy   #include <IOSTREAM> //#include <WINSOCK.H> using std; typedef  uint16; unsigned   ...

  6. htonl(),htons(),ntohl(),ntons()--大小端模式转换函数

    不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian). 大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处. 小端模 ...

  7. ntohs, ntohl, htons,htonl的比较和详解

    在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题. 这时就可能用到htons(), ntohl(), ntohs(),htons()这4个网络字节顺序与本地字节顺序之间的转换函数 ...

  8. 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= ...

  9. 接口处理篇 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/ ...

随机推荐

  1. 1003. Emergency

    As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...

  2. ACM水题

    ACM小白...非常费劲儿的学习中,我觉得目前我能做出来的都可以划分在水题的范围中...不断做,不断总结,随时更新 POJ: 1004 Financial Management 求平均值 杭电OJ: ...

  3. scala 学习笔记(03) 参数缺省值、不定个数参数、类的属性(Property)、泛型初步

    继续学习,这一篇主要是通过scala来吐槽java的,同样是jvm上的语言,差距咋就这么大呢? 作为一个有.NET开发经验的程序员,当初刚接触java时,相信很多人对java语言有以下不爽(只列了极小 ...

  4. Linux学期总结

    学习笔记链接 第一次 http://www.cnblogs.com/Spr1ngxx/p/4823573.html 第二次 http://www.cnblogs.com/Spr1ngxx/p/4842 ...

  5. 简单高效的nodejs爬虫模型

    这篇文章讲解一下yunshare项目的爬虫模型. 使用nodejs开发爬虫很简单,不需要类似python的scrapy这样的爬虫框架,只需要用request或者superagent这样的http库就能 ...

  6. sql server存储过程编程

    存储过程是一组完成特定功能的SQL 语句集合,经编译后存储在数据库中.   存储过程作为一个单元进行处理并以一个名称来标识.它能向用户返回数据.向数据库表中写入或修改数据等操作. 用户通过指定存储过程 ...

  7. SQLServer数据导入Mongodb

    一.思路 MongoVUE免费版支持MySQL导入Mongo,所以思路是SQLServer导入MySQL,再从MySQL导入Mongo. 二.准备 1,安装mysql数据库(我用的是WAMP,集成my ...

  8. Bootstrap系列 -- 13. 内联表单

    有时候我们需要将表单的控件都在一行内显示.在Bootstrap框架中实现这样的表单效果是轻而易举的,你只需要在<form>元素中添加类名“form-inline”即可 如果你要在input ...

  9. Android之Activity启动模式

    正常模式 每个应用都有一个任务栈,任务栈中保存着已创建的Activity,先创建的Activity先入栈,栈顶是当前正在显示的activity(running),这是正常模式下的Activity的管理 ...

  10. Rootkit Hunter恶意程序查杀

    恶意程序,恶意代码检测 下载:https://pkgs.org/search/rkhunter 安装:rpm -ivh rkunter* Installed: #需要先安装  lsof.x86_64 ...