a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 74|回复: 0

[综合辅导] Linux认证:Linux网络编程中的地址问题

[复制链接]
发表于 2012-8-4 12:07:07 | 显示全部楼层 |阅读模式
Linux认证:Linux网络编程中的地址问题
" J8 f# m& Y6 s7 q& `平时我们使用的IP地址是192.168.1.11这种类型的字符串;而在Linux内核中是用二进制方式表达的IP地址。在程序设计中经常要用到字符串表达方式的IP地址和二进制的IP地址之间的转换。7 ]! b* y2 P: f
面对网络编程中众多的地址函数,你hold住了么,tiger哥没hold住,所以就写了此篇文章,希望大家能hold住网络编程。
/ G: V6 K: d( g* z. v9 c0 |1 ~前言:结构体struct in_addr结构struct in_addr 在文件中定义,结构in_addr 有一个unsigned long int 类型的成员变量s_addr.通常所说的IP地址的二进制形式就保存在成员变量s_addr中。( S8 @4 A' Z' I' ?7 W  R
结构struct in_addr的原型如下:structin_addr{ unsigned long int s_addr;/*IP地址*/ }一。字符串IP地址转换为二进制形式的IP地址函数1.inet系列函数的原型:#include #include #include int inet_aton(const char *cp,struct in_addr *inp);int addr_t inet_addr(const char *cp);int addr_t inet_network(const char *cp);char * inet_ntoa(struct in_addr in);struct in_addr inet_makeaddr(int net,int host);in_addr_t inet_lnaof(struct in_addr in);in_addr_t inet_netof(struct in_addr in);2.inet_aton()函数int inet_aton(const char*cp,struct in_addr *inp)
* ]# l9 N" ~2 b2 t, V( `8 d1 P: o- ]1》函数作用:inet_ation()函数将在cp中存储的点分十进制字符串类型的IP地址,转换为二进制的IP地址,转换后的值保存在指针inp指向的结构struct in_addr中。
! ?; ~: t6 z0 U! o7 ]1 P2》形参? const char *cp:指向字符类型的IP地址。例如“192.168.1.11”? struct in_addr *inp:指向二进制的网络字节顺序的IP地址structin_addr{ unsignedlong s_addr } 3》函数执行成功则返回非0值,参数无效则返回0. 4》实例:#include #include #include
. P' g- W6 s7 D& N: A6 q#include #include #include int main()
8 o! T+ Y5 J+ K! n7 s! y: C{ char buffer[32];structin_addr in;in.s_addr =0;/*输入一个字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IP地址:%s\n”,buffer);if( 0 == inet_aton(buffer,&in)){ perror(“inet_aton”);exit(1);} else { printf(“after transfer:0x%0x\n”,in.s_addr);} 5》 inet_aton函数最后计算出来的是网络字节序的二进制IP 3.inet_addr()函数in_addr_t inet_addr(const char *cp)
" t8 _% A& g. w1》函数作用:它将参数cp所指向的字符串形式的IP地址(“192.168.1.11”)转换为二进制的网络字节序的IP地址形式该函数的缺点是:如果IP地址是255.255.255.255.那么调用inet_addr()函数后将返回-1(因为-1的补码形式是0xFFFFFFFF)。所以不建议使用inet_addr()函数,而是使用inet_aton()函数。  f; K0 |+ k& E
2》函数形参:const char*cp:cp指向字符串形式的IP地址。
  l+ Z1 O. r* P( d+ Q3》函数返回值:函数成功后返回二进制的网络字节序的IP地址(struct in_add),否则返回-1. 4》inet_addr计算出来的是网络字节序的二进制IP 5》函数实例:#include #include #include
6 c! G' I+ L+ u! c+ S#include #include #include int main()
. G/ r" C/ W1 l* H5 T{ char buffer[32];structin_addr in;in.s_addr =0;/*输入一个字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IPaddress:%s\n”,buffer);if((in.s_addr = inet_addr(buffer))==INADDR_NONE){ perror(“inet_addr”);exit(1);} else { printf(“after transfer:0x%0x\n”,in.s_addr);} 4.inet_network in_addr_t inet_network(constchar *cp)1 H$ S' h, _$ J# `; d
1》函数作用:将参数cp指向的字符串形式的网络地址转换为主机字节顺序形式的二进制IP地址。
0 Z+ R0 D$ O3 q3 @& x. i- c4 a! W2》函数形参? const char *cp: cp指向字符串形式的IP地址。* r, t  y$ \/ `) s- e$ V6 H& Z8 ?0 w
3》函数返回值:执行成功后返回转换后的结果,参数无效后返回-1. 4》inet_network返回的是主机字节序5》函数实例:#include #include #include+ K) K% k: A& a5 x+ `
#include #include #include int main(): H5 G( G9 @8 ^$ o2 v
{ char buffer[32];structin_addr in;in.s_addr =0;/*输入一个字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IPaddress:%s\n”,buffer);if((in.s_addr = inet_addr(buffer))==INADDR_NONE){ perror(“inet_addr”);exit(1);} else { printf(“after transfer:0x%0x\n”,in.s_addr);}总结:1.inet_addr和inet_network函数都是用于将字符串形式转换为整数形式用的;2.inet_addr返回的整数形式是网络字节序,而inet_network返回的整数形式是主机字节序。8 I' b  ~7 `  f% z, N' Z7 ?
3.inet_addr 和inet_network有一个小缺陷,那就是当IP是255.255.255.255时,这两个函数会认为这是个无效的IP地址,这是历史遗留问题,其实在目前大部分的路由器上,这个 255.255.255.255的IP都是有效的。! F' _* N! v8 c# t* _% z& [( V
4.inet_aton认为255.255.255.255是有效的,所以建议使用inet_aton.并且inet_aton函数返回的是网络字节序的IP地址。
. l5 N; w9 e8 w% k. ?  c二。进制IP地址转换为字符串形式的IP地址1.char * inet_ntoa(struct in_addr in);1》函数作用:将数值为in的网络字节序形式的二进制IP地址转换为字符串形式的IP地址。
) S. j$ B% G# o0 J0 u2》形参:struct in_addr in:指向二进制的IP地址3》函数返回值:执行成功返回结果字符串的指针,参数无效返回NULL. 4》函数实例:#include #include #include
& g- Y6 A- _' T: B9 L#include #include #include int main()# V6 b" n5 N, {$ D( R+ O; N
{ char buffer[32];char *str;structin_addr in;in.s_addr =0;/*输入一个字符串形式的IP地址*/ printf(“pleaseinput the ip addrss\n”);scanf(“%s”,buffer);buffer[31]=‘\0’;printf(“original IP地址:%s\n”,buffer);if( 0 == inet_aton(buffer,&in)){ perror(“inet_aton”);exit(1);} else { printf(“the first transfer:0x%0x\n”,in.s_addr);} printf(“begin two process:\n”);if( (str =inet_ntoa(in) == NULL ){ printf(“inet_ntoa:argumentinvalid\n”);} else { printf(“thesecond transfer:%s\n”,str);}说明:1.函数inet_ntoa()的返回值为一个指向字符串的指针,该内存函数inet_ntoa()每次调用都会重新覆盖,因此函数不安全,可能存在某种隐患2.实例:#include #include #include
# r% y7 t8 x6 @! f# C+ H# L1 Q#include #include #include int main()
+ R' Y( V, f9 {8 Z( m! ]{ structin_addr ip1,ip2;char *str1 ;char *str2;ip1.s_addr = 192《《24| 168 《《16 |1 《《8 | 1;ip2.s_addr =255《《24 | 255 《《16 |255《《8|255;str1 = inet_ntoa(ip1);str2 = inet_ntoa(ip2);printf(“ip1:0x%xà%s\n”,ip1.s_addr,str1);printf(“ip2:0x%xà%s\n”,ip2.s_addr,str2);}输出结果为:ip1: 0xc0a80101à255.255.255.255;ip2:0xffffffffà255.255.255.255;表明函数inet_ntoa在进行二进制IP地址到字符串IP地址的转换过程中是不可重入的,这个函数转换两个不同的IP地址得到了同一个结果。此类函数在调用之后,需要立即将结果取出,没有取出结果之前不能进行同样函数的调用。
& v) r5 T4 e) ^3 B: `$ z. x7 x8 j" h) S三。最新的地址转换函数inet_pton()和inet_ntop()函数inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6.算是比较新的函数了。inet_pton函数原型如下[将“点分十进制” -》 “整数”],并且这两个函数是一套安全的协议无关的地址转换函数。所谓安全即这两个函数是可重入的,并且这些函数支持多种地址类型,包括IPv4和IPv6. 1.inet_pton()函数1》函数功能inet_pton()函数将字符串类型的IP地址转换为二进制类型。
7 y( k7 s9 z8 l$ I0 M, [# f2 i2》函数原型#include #include #include intinet_pton(int af, const char *src, void *dst);3》函数形参:? int af:af表示网络类型的协议族,在IPv4下的值为AF_INET;? src:存放需要转换的字符串? dst :存放转换后的结果,在IPv4下,dst指向结构struct in_addr的指针。2 N" P2 [9 A! f% B
4》函数返回值当函数inet_pton()的返回值为-1的时候,通常是用于af所指定的协议族不支持造成,此时errno的返回值为EAFNOSUPPORT;当函数的返回值为0时,表示src指向的值不是合法的IP地址;当函数的返回值为正值时,表示转换成功。
( q! ~5 j6 ~" `2.inet_ntop()函数1》函数功能inet_pton()函数将二进制的网络IP地址转换为字符串。( I( q" A! c0 H3 c" s$ Y
2》函数原型:#include #include #include intinet_nton(int af, const void *src, char *dst,socklen_t cnt);3》函数形参:? int af:af表示网络类型的协议族,在IPv4下的值为AF_INET;? src :为需要转换的二进制IP地址,在IPv4下,src指向一个structin_addr结构类型的指针。? dst指向保存结果缓冲区的指针? cnt的值是dst缓冲区的大小4》函数返回值Inet_ntop()函数返回一个指向dst的指针。当发生错误时,返回NULL.当af设定的协议族不支持时,errno设置为EAFNOSUPPORT;当dst缓冲区大小过小的时候errno的值为ENOSPC. 3.函数实例:#include #include #include5 j4 Y$ g6 c" M/ ^' O8 l7 ^
#include #include #include int main(int argc,char *argv[])
5 ^- J2 v* G* @; c# f& d* T4 }{ struct in_addr ip;char ipstr[] = “192.168.1.1”;char addr[ADDRLEN];const char * str = NULL;int err = 0;if(err 》 0){ printf(“inet_pton:ip %s value is :0x%x\n”,ipstr,ip.s_addr);} //把192.168.12.255转换为网络字节序ip.s_addr = htonl(192 《《 24 | 168《《16 | 12《《8 | 255);str = (const char *)inet_ntop(AF_INET,(void*)&ip,(char *)&addr[0],ADDRLEN);if(str){ printf(“inet_ntop :ip 0x%x is%s\n”,ip.s_addr,str);}四。inet_makeaddr()函数,inet_lnaof()函数和inet_netof()函数1.struct in_addr inet_makeaddr(int net,int host)
# H: K3 {  f' }9 y- H1》函数功能:一个主机的IP地址分为网络地址和主机地址,inet_makeaddr()函数将主机字节序的网络地址net和主机地址host合并成一个网络字节序的IP地址。# y2 m, }- x% p8 p
2》函数形参:? int net:存放网络号参数(二进制形式的主机字节序)? int host:存放主机号地址(二进制形式的主机字节序)
# d8 v( N( \2 H, j/ z3》函数返回值:返回一个网络字节序的IP地址4》函数实例:unsigned long net,host;net = 0x0000007F;host = 0x00000001;struct in_addr ip = inet_makeaddr(net,hst);2.in_addr_t inet_lnaof(struct in_addr in)" I+ ^" Q: f5 W6 p: D% e$ @+ Z/ z
1》函数功能:该函数从参数in中提取出主机地址,执行成功后返回主机字节顺序形式的主机地址。
  A9 m, f. `6 s' m& k例如:172.17.242.131属于B类地址,则主机号为低16位,主机地址为0.0.242.131,按主机字节顺序输出则为0xf283. 2》函数形参? struct in_addr in:in存放的是主机字节序的二进制形式的IP地址3》函数返回值:返回主机字节序的二进制形式的IP主机部分的数值4》函数实例:const char *addr = “127.0.0.1”;unsigned long ip = inet_network(addr);unsigned long host_id = inet_lnaof(ip);3.in_addr_t inet_netof(struct in_addr in)
, B: x8 T  I  P# c& ^1》函数功能:该函数从参数in中提取出网络地址,执行成功后返回主机字节顺序形式的网络地址。
" \/ r2 J9 s$ Y  u" }5 ~如:172.17.242.131属于B类地址,则高16位表示网络号,网络地址为172.17.0.0. 2》函数形参? struct in_addr in:in存放的是主机字节序的二进制形式的IP地址3》函数返回值:返回主机字节序的二进制形式的IP网络部分的数值4》函数实例:const char *addr = “127.0.0.1”;unsigned long ip = inet_network(addr);unsigned long network_id = inet_netof(ip);
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-17 22:06 , Processed in 0.180729 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表