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

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

  1. # if __BYTE_ORDER == __BIG_ENDIAN
  2. /* The host byte order is the same as network byte order,
  3. so these functions are all just identity. */
  4. # define ntohl(x) (x)
  5. # define ntohs(x) (x)
  6. # define htonl(x) (x)
  7. # define htons(x) (x)
  8. # else
  9. # if __BYTE_ORDER == __LITTLE_ENDIAN
  10. # define ntohl(x) __bswap_32 (x)
  11. # define ntohs(x) __bswap_16 (x)
  12. # define htonl(x) __bswap_32 (x)
  13. # define htons(x) __bswap_16 (x)
  14. # endif
  15. # endif
  16. #endif

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

  1. /* Swap bytes in 32 bit value. */
  2. #define __bswap_constant_32(x) \
  3. ((((x) & 0xff000000u) >> ) | (((x) & 0x00ff0000u) >> ) | \
  4. (((x) & 0x0000ff00u) << ) | (((x) & 0x000000ffu) << ))

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

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

  1. union
  2. {
  3. unsigned int ber32;
  4. char mem[];
  5. } currentData;

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

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

  1. #if BYTE_ORDER == BIG_ENDIAN
  2. #warning "BIG_ENDIAN SYSTEM!"
  3. currentData.ber32 = sampleValue;
  4. #elif BYTE_ORDER == LITTLE_ENDIAN
  5. #warning "LITTLE_ENDIAN SYSTEM!"
  6. currentData.ber32 = bswap_32(sampleValue);
  7. #else
  8. #error "No BYTE_ORDER is defined!"
  9. #endif
  10. sendBuf[bufPos++] = currentData.mem[];
  11. sendBuf[bufPos++] = currentData.mem[];
  12. sendBuf[bufPos++] = currentData.mem[];
  13. sendBuf[bufPos++] = currentData.mem[];

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

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

  1. sampleValue = ;
  2.  
  3. sampleValue += (buff[posOfSamples + 0] << (8 * 3)) );
  1. sampleValue += (buff[posOfSamples + 1] << (8 * 2)) );
  1. sampleValue += (buff[posOfSamples + 2] << (8 * 1)) );
  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. ORACLE 定时执行存储过程

    推荐用dbms_scheduler方式更好 (2012-11-19注) /* 查询: select job,broken,what,interval,t.* from user_jobs t; job ...

  2. ZooKeeper 笔记(2) 监听数据变化

    ZK中的每个节点都可以存储一些轻量级的数据,这些数据的变化会同步到集群中的其它机器.在应用中程序员可以添加watcher来监听这些数据的变化,watcher只会触发一次,所以触发过后想要继续监听,必须 ...

  3. C8051逆向电阻屏:头儿拍脑袋说电阻屏IC好赚钱3块钱成本能卖20几块。,一个月不分昼夜逆向成功后头儿说电阻屏已经被市场淘汰请放弃治疗。

    参考: 书籍,<圈圈教你玩USB>  C8051F单片机快速入门:http://www.waveshare.net/Left_Column/C8051F_Application_Notes ...

  4. retrofit2中ssl的Trust anchor for certification path not found问题

    在retrofit2中使用ssl,刚刚接触,很可能会出现如下错误. java.security.cert.CertPathValidatorException: Trust anchor for ce ...

  5. 深入理解计算机系统(2.2)---布尔代数以及C语言上的位运算

    布尔代数上的位运算 布尔代数是一个数学知识体系,它在0和1的二进制值上演化而来的. 我们不需要去彻底的了解这个知识体系,但是里面定义了几种二进制的运算,却是我们在平时的编程过程当中也会遇到的.这四种运 ...

  6. 通过Ajax实现增删改查

    项目链接:https://github.com/shuai7boy/Ajax_CRUD 简要截图:

  7. C 语言学习的第 02 课:C 语言的开发环境

    工欲善其事,必先利其器.不知道还是不是记得上一篇文章中说到的,计算机本身是一个数据输入及输出的设备.所以,为了将你大脑中的各种 idea 输入到电脑,且最终生成能够执行的程序,总是要预备点什么的. 通 ...

  8. C程序两则

    <span style="font-size:24px;">#include<iostream> using namespace std; int *fun ...

  9. WEB 文件上传

    关键:<input name="file" type="file"/> 然后,在外面<form>层中必须写上:enctype=" ...

  10. android 调用电话功能

    今天用到了打电话的功能,这要如何实现呢? 很简单 1.创建对应对的xml展示页面喝java文件 2.在manifest中添加权限 下面上代码吧: 这是布局的一部分 <LinearLayout a ...