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

在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。

这时就可能用到htons(), ntohl(), ntohs(),htons()这4个网络字节顺序与本地字节顺序之间的转换函数:

htonl()–“Host to Network Long int” 32Bytes

ntohl()–“Network to Host Long int” 32Bytes

htons()–“Host to Network Short int” 16Bytes

ntohs()–“Network to Host Short int” 16Bytes

之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO。

网络字节顺序NBO(Network Byte Order):

按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题(大端:低位存放在高字节)。

主机字节顺序(HBO,Host Byte Order):

不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关(小端:低位存放在低字节)。

如 Intel x86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12 。

如IBM power PC结构下,short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78。

由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power pc那样的顺序 。在PC开发中有ntohl和htonl函数可以用来进行网络字节和主机字节的转换。

在Linux系统下:htonl(),htons(), ntohl(), ntohs()的头文件及函数定义:

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

在windows系统下:htonl(),htons(), ntohl(), ntohs(), inet_addr()使用说明

ntohs()
  简述:

将一个无符号短整形数从网络字节顺序转换为主机字节顺序。

#include <winsock.h>

u_short PASCAL FAR ntohs( u_short netshort);

netshort:一个以网络字节顺序表达的16位数。

注释:

本函数将一个16位数由网络字节顺序转换为主机字节顺序。

返回值:ntohs()返回一个以主机字节顺序表达的数。

ntohl()
  简述:

将一个无符号长整形数从网络字节顺序转换为主机字节顺序。

#include <winsock.h>

u_long PASCAL FAR ntohl( u_long netlong);

netlong:一个以网络字节顺序表达的32位数。

注释:

本函数将一个32位数由网络字节顺序转换为主机字节顺序。

返回值:

ntohl()返回一个以主机字节顺序表达的数。

htons()
  简述:

将主机的无符号短整形数转换成网络字节顺序。//将无符号短整型主机字节序转换为网络字节序

#include <winsock.h>

u_short PASCAL FAR htons( u_short hostshort);

hostshort:主机字节顺序表达的16位数。

注释:

本函数将一个16位数从主机字节顺序转换成网络字节顺序。

返回值:

htons()返回一个网络字节顺序的值。

简单地说,htons()就是将一个数的高低位互换

(如:12 34 --> 34 12)

VB表示:

MsgBox Hex(htons(&H1234))

显示值为 3412

htonl()
  简述:

将主机的无符号长整形数转换成网络字节顺序。//将无符号长整型网络字节序转换为主机字节序

#include <winsock.h>

u_long PASCAL FAR htonl( u_long hostlong);

hostlong:主机字节顺序表达的32位数。

注释:

本函数将一个32位数从主机字节顺序转换成网络字节顺序。

返回值:

htonl()返回一个网络字节顺序的值。

inet_addr()
  简述:

将一个点间隔地址转换成一个in_addr。

#include <winsock.h>

unsigned long PASCAL FAR inet_addr( const struct FAR* cp);

cp:一个以Internet标准“.”间隔的字符串。例如202.38.214.xx

当IP地址为255.255.255.255是被认为无效IP地址。

本函数解释cp参数中的字符串,这个字符串用Internet的“.”间隔格式表示一个数字的Internet地址。

返回值:

一个无符号长整形数,可用作Internet地址。所有Internet地址以网络字节顺序返回(字节从左到右排列)。

——————————————————————————

in_addr实现原理:

输入是点分的IP地址格式(如A.B.C.D)的字符串,从该字符串中提取出每一部分,转换为ULONG,假设得到4个ULONG型的A,B,C,D,

ulAddress(ULONG型)是转换后的结果,

ulAddress = D<<24 + C<<16 + B<<8 + A(网络字节序),即inet_addr(const char *)的返回结果

实现:inet_addr(“11.12.13.25”)

另外,我们也可以得到把该IP转换为主机序的结果,转换方法一样

A<<24 + B<<16 + C<<8 + D

实现:ntohl(inet_addr(“11.12.13.25”));

我认为它把A,B,C,D都存储在静态的变量里了。所以,最好先把获取的结果存起来。

long ip1 = inet_addr(“11.11.11.11”);

long ip2 = inet_addr(“22.22.22.22”);

然后再使用ip1和ip2

——————————————————————————

inet_ntoa()
  简述:

将网络地址转换成“.”点隔的字符串格式。

#include <winsock.h>

char FAR* PASCAL FAR inet_ntoa( struct in_addr in);

in:一个表示Internet主机地址的结构。

注释:

本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。

当IP地址为255.255.255.255是认为有效IP地址。这是与inet_addr()的区别

返回值:

若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NULL。其中的数据应在下一个WINDOWS套接口调用前复制出来。

inet_aton()

与inet_ntoa()作用相反。

inet_pton()

简述:

本函数将点分十进制转换为整数

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

int inet_pton(int af, const char *src, void *dst);

这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中

inet_pton 是inet_addr的扩展,支持的多地址族有下列:

af = AF_INET

src为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址

转换为in_addr的结构体,并复制在*dst中

af =AF_INET6

src为指向IPV6的地址,,函数将该地址转换为in6_addr的结构体,并复制在*dst中

如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0。

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);

这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt,他是所

指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC

atoi()

array to integer将字符串转换为整形数

首先,假设你已经有了一个sockaddr_in结构体ina,你有一个IP地址"132.241.5.10" 要储存在其中,你就要用到函数inet_addr(),将IP地址从 点数格式转换成无符号长整型。

使用方法如下:

ina.sin_addr.s_addr = inet_addr(“132.241.5.10”);

注意,inet_addr()返回的地址已经是网络字节格式,所以你无需再调用 函数htonl()。

我们现在发现上面的代码片断不是十分完整的,因为它没有错误检查。 显而易见,当inet_addr()发生错误时返回-1。记住这些二进制数字?(无符 号数)-1仅仅和IP地址255.255.255.255相符合!这可是广播地址!大错特 错!记住要先进行错误检查。

好了,现在你可以将IP地址转换成长整型了。有没有其相反的方法呢? 它可以将一个in_addr结构体输出成点数格式? 这样的话,你就要用到函数 inet_ntoa()(“ntoa"的含义是"network to ascii”),就像这样:

printf("%s",inet_ntoa(ina.sin_addr));

它将输出IP地址。需要注意的是inet_ntoa()将结构体in-addr作为一 个参数,不是长整形。同样需要注意的是它返回的是一个指向一个字符的 指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用 inet_ntoa(),它就将覆盖上次调用时所得的IP地址。例如:

char *a1, *a2;

a1 = inet_ntoa(ina1.sin_addr); /* 这是198.92.129.1 */

a2 = inet_ntoa(ina2.sin_addr); /* 这是132.241.5.10 */

printf("address 1: %s ",a1);

printf("address 2: %s ",a2);

输出如下:

address 1: 132.241.5.10

address 2: 132.241.5.10

假如你需要保存这个IP地址,使用strcopy()函数来指向你自己的字符指针。

*******************************************************************

测试代码如下

#include

#include

#include

#include

#include

int main(int argc, char* argv[])

{

struct in_addr addr1,addr2;

ulong l1,l2;

l1= inet_addr(“192.168.0.74”);

l2 = inet_addr(“211.100.21.179”);

memcpy(&addr1, &l1, 4);

memcpy(&addr2, &l2, 4);

printf("%s : %s ", inet_ntoa(addr1), inet_ntoa(addr2)); //注意这一句的运行结果

printf("%s ", inet_ntoa(addr1));

printf("%s ", inet_ntoa(addr2));

return 0;

}

实际运行结果如下:

192.168.0.74 : 192.168.0.74 //从这里可以看出,printf里的inet_ntoa只运行了一次。

192.168.0.74

211.100.21.179

inet_ntoa返回一个char *,而这个char *的空间是在inet_ntoa里面静态分配的,所以inet_ntoa后面的调用会覆盖上一次的调用。第一句printf的结果只能说明在printf里面的可变参数的求值是从右到左的,仅此而已。

ntohs, ntohl, htons,htonl相关推荐

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

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

  2. 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位 hto ...

  3. ntohs, ntohl, htons,htonl字节序转换函数

    ntohs() 简述:将一个无符号短整型数从网络字节顺序转换为主机字节顺序.(16位). #include <netinet/in.h> uint16_t ntohs(uint16_t n ...

  4. linux c ntohs, ntohl, htons,htonl 网络字节序转换函数

    ntohs() 简述:将一个无符号短整型数从网络字节顺序转换为主机字节顺序.(16位). #include <netinet/in.h> uint16_t ntohs(uint16_t n ...

  5. ntohs, ntohl, htons,htonl inet_aton等详解

    ntohs =net to host short int 16位 htons=host to net short int 16位 ntohs =net to host long int 32位 hto ...

  6. htonl(), ntohl(), htons(), ntohs() 函数

    转自:http://www.cnblogs.com/s7vens/archive/2011/12/12/2284892.html 在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题 ...

  7. htonl(), ntohl(), htons(), ntohs() 函数具体应用

    htons和htonl函数具体应用 htons和htonl函数,是用来将主机字节顺序转换为网络字节顺序 在进行网络抓包时,抓到的包的数据是网络字节顺序,在进行编程时,要进行主机字节顺序和网络字节顺序间 ...

  8. htons(), htonl(), ntohs(), ntohl()

    在网络编程中,往往会遇到字节的网络顺序和主机顺序的问题. 我们先来了解下字节的网络顺序和主机顺序: 网络字节序与主机字节序 主机字节序:就是我们平常说的大端和小端模式,不同的CPU有不同的字节序类型, ...

  9. htonl ntohl htons ntohs

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

最新文章

  1. Selenium 2.0的由来及设计架构(三)
  2. python 日志模块 logging
  3. 所有人问「贴吧之父」俞军
  4. ERROR 1045 (28000): Access denied for user root@localhost (using password:
  5. BZOJ 2822: [AHOI2012]树屋阶梯 [Catalan数 高精度]
  6. perl脚本执行linux命令行,Perl调用shell命令方法小结
  7. 根据Ping(ICMP协议)得到TTL并分析
  8. 安全云盘项目(一):1.5 bufferevent服务端代码事件策略
  9. 编程语言_JavaScript_面试题004
  10. linux查看共享内存max,浅析Linux的共享内存与tmpfs文件系统
  11. js中按钮去触发定时器,那么多次点击这个定时器会越来越快,解决方法
  12. django学习第一天
  13. SPOJ Problem 2178:He is offside!
  14. 织梦木马 data.php,DedeCMS后门木马专杀工具V2.0
  15. 添加引用提示:未能找到引用的组件“XXX”。未能加载类型库。加载类型库/DLL 时出错。...
  16. Linux系统如何替换新硬盘
  17. PageOffice中如何调用ZoomSeal签章系统中的印章
  18. 如何摆脱NAS中的振动和噪音
  19. Fragment嵌套Fragment
  20. WAF与IPS的区别

热门文章

  1. Opengl的一些常用功能理解
  2. arcgis engine 入门难点——什么是接口查询(QueryInterface)
  3. 【Python】Numpy简明教程
  4. Python实现音标代码算法
  5. 嵌入式AI智能技术液体颗粒计数器
  6. 用python开发一个记账的微信公众号
  7. mysql workbench批量导出导入sql文件
  8. 红米k20 android版本,红米k20pro入手哪个版本好 红米k20pro哪个更值得入手
  9. python+selenium+webdriver
  10. 远程服务连接工具—FinallShell