Chinaunix首页 | 论坛 | 博客
  • 博客访问: 589124
  • 博文数量: 199
  • 博客积分: 5087
  • 博客等级: 大校
  • 技术积分: 2165
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-26 21:53
文章存档

2010年(199)

我的朋友

分类: 系统运维

2010-05-25 23:04:10

ipv6 基础知识及SOCKET编程

1.IPV6点分地址表达

 

    从 IPv4 IPv6 最明显的变化就是网址的长度不同了,IPv6 地址长度为128比特而 IPv4 地址长度为32比特。所有 IPv6 地址的个数可达3.4x1038个。

 

1.1 IPv6 地址格式

 

   IPv6 地址在许多情况下都由两个逻辑部分组成:64位的网络前缀部分和64位的主机寻址部分,而后者通常都是主机依照 MAC 接口地址自动生成的。IPv6 地址由8组长度为16比特的十六进制数值组成,各组之间由

冒号(:)分隔开,示例如下

  aaaa : aaaa : aaaa : aaaa : aaaa : aaaa : aaaa : aaaa

 

其中每一个aaaa, 一组长度为16比特的十六进制数,而 a 是一位长度为4比特的十六进制数值,以下就是个IPV6的实例.

 

3ffe:ffff:100:f101:210:a4ff:fee3:9566

 

 

1.2 ipv6 地址变形:

 

  因为IPV6地址位数太多.因此如果出现全零的段(0000),可以省写为 0,这个跟IPV4一样.

 

  如果出现连续的全0,还可以直接写成::,1080:0:0:0:8:810:213C:123A地址可以省写为 

1080::8:810:213C:123A,但这种写法在一个地址里只能出现一次.比如本地回环地址: 它的简写就是::1  等同于ipv4 127.0.0.1

 

      还有一种表达法也是常用. 可以用“IPv6地址/前缀长度”来表示地址前缀. 前缀长度是一个十进制值,指定该地址中最左边的用于组成前缀的位数. 址前缀在一定意义上代表了这个IP地址的类型.

 

 例如: 假如一个IP地址它的地址前缀为16位,IP地址为“1080::8:810:213C:123A”,则用地址前缀法表示就为:1080::8:810:213C:123A/32

 

后四个 8 位可使用十进制来表示 IPv4 地址。 例如,一个与 IPv6 相一致的 IPv4 地址为 : 0:0:0:0:0:0.192.168.0.1

 

 

决定这些IP地址类型的“地址前缀”(Format Prefix FP)。顾名思义,地址前缀就是在地址的最前面那段数字。当然也属于128位地址空间范围之中,通过不同的地址前缀来代表不同的地址类型。类似于IPV4子网掩码.

 

   前缀数的换算,/32对应的地址数量为2的(128-32)次方=296次方个,/48对应的地址数量为2的(128-48)次方=280次方个,/128对应的地址数量为2的(128-128)次方=1个地址。  232次方对应的地址数量约为40亿个。

 

1.3 所有IPV6地址变形总结

(a): 前头的零可以去掉。

(b):0000 = 0 (压缩排列)。

(c): :: ”代表一组或多组 16 位零,并且在一个地址中仅能出现一次。 例如: 2001:0:13FF:09FF:0:0:0:0001 = 2001:0:13FF:09FF::1

 

(d): 后四个 8 位可使用十进制来表示 IPv4 地址。 例如,一个与 IPv6 相一致的 IPv4 地址为 : 0:0:0:0:0:0.192.168.0.1

 

 

2.Ipv6网络的使用

 

Linux 对IPV6的支持已经非常完善了,在我的RHEL机器上.

ifconfig 会显示IPV6地址.

 

ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0C:29:51:C6:5F
          inet addr:192.168.2.151  Bcast:192.168.2.255 
Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe51:c65f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:156802 errors:0 dropped:0 overruns:0 frame:0
          TX packets:121246 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:146606620 (139.8 MiB)  TX bytes:79355802 (75.6
MiB)
          Interrupt:169 Base address:0x2000
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:7675 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7675 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4329827 (4.1 MiB)  TX bytes:4329827 (4.1 MiB)

 

Ipv6网络不能使用ping 来测试网络,而是采用ping6 来处

,注意地址不能带地址前缀(/32之类)

 

[root@rhel5 ~]# ping6 ::1

PING ::1(::1) 56 data bytes

64 bytes from ::1: icmp_seq=0 ttl=64 time=2.93 ms

64 bytes from ::1: icmp_seq=1 ttl=64 time=0.176 ms

64 bytes from ::1: icmp_seq=2 ttl=64 time=0.057 ms

64 bytes from ::1: icmp_seq=3 ttl=64 time=0.038 ms

64 bytes from ::1: icmp_seq=4 ttl=64 time=0.052 ms

--- ::1 ping statistics ---

5 packets transmitted, 5 received, 0% packet loss, time 4003ms

rtt min/avg/max/mdev = 0.038/0.651/2.934/1.142 ms, pipe 2

 

用ping6 来拼其它机器,因为一般LINUX不带IPV6路由,因此必须用-I 指过从哪一个块网卡发出IPV6

ping6 fe80::225:86ff:fe92:49b8 -I eth0
PING fe80::225:86ff:fe92:49b8(fe80::225:86ff:fe92:49b8) from fe80::21d:fff:fe28:97c8 eth0: 56 data bytes
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=0 ttl=64 time=1.95 ms
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=1 ttl=64 time=0.162 ms
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=2 ttl=64 time=0.162 ms
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=3 ttl=64 time=0.166 ms
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=4 ttl=64 time=0.164 ms
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=5 ttl=64 time=0.159 ms
64 bytes from fe80::225:86ff:fe92:49b8: icmp_seq=6 ttl=64 time=0.166 ms

--- fe80::225:86ff:fe92:49b8 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 6011ms
rtt min/avg/max/mdev = 0.159/0.418/1.953/0.626 ms, pipe 2

 

3.IPV6 包结构

 

IPv4IPv6包头结构比较 

IPv4中所有包头以32个字节为单位,即基本的长度单位是4个字节。表1IPv4的包头格式。

  IPv6中,包头以64个字节为单位,且包头的总长度是40个字节。IPv6的包头格式如表2所示。

  比较两种包头格式可知,IPv6IPv4进行了较大改进:

 

  首先,取消了IPv4包头的6个字段:IP包头长度(Header Length)、服务类型(Service Type)、标识(Identification)、标志(Flag)、标志偏移量(Fragment Offset)及头标校验和(Header Checksum)

 

  其次,在IPv6中有三个控制字段重新命名,并在一些条件下重新定义:长度(Length)、服务类型(Service Type)、生存时间(Time to Live)

 

最后,增加了两个新的字段:优先级(Priority)和流标识(Flow Label)

 

以下是实际抓包通讯

 

4.IPV6 Socket 编程

 

IPV6除了地址处理和创建socket之外,其余编程都跟IPV4 类似.

4.1 创建IPV6 Socket ,domain采用 PF_INET6.

socket(PF_INET6,SOCK_STREAM,0);

 

4.2 IPV6 Socket 地址表示.使用struct sockaddr_in6 .注意它的尺寸大于 struct sockaddr addr,地址族使用AF_INET6

 

 

 

struct in6_addr {

 uint8_t s6_addr[16]; /* 128 bit 字节地址 */

};
#define SIN6_LEN /* required for compile-time tests */

struct sockaddr_in6 {
 uint8_t sin6_len; /* = SIN6_LEN */
 sa_family_t sin6_family; /* = AF_INET6 */
 in_port_t sin6_port; /* */
 uint32_t sin6_flowinfo; /* priority and flow label */
 struct in6_addr sin6_addr; /* IPV6 的任意地址是 in6addr_any */
};

 

struct sockaddr_in6 server_addr;

memset((void *)&server_addr,0,sizeof(server_addr));

    server_addr.sin6_family = AF_INET6 ; /* ipv6 */
      server_addr.sin6_port = htons(port);

     len =inet_pton(AF_INET6, ip, (void *)&(server_addr.sin6_addr));

 
4.3 IPV6 地址转换
  包含两种转换一种是点分法转socket地址.
  另外是一种逆运算。
 

/* 点分转socket 地址*/
len =inet_pton(AF_INET6, ip, (void *)&(server_addr.sin6_addr));
/* socket 地址转点分 */
fprintf(stdout,"client connect: ip %s,port %d\n",inet_ntop(AF_INET6, (void *)&(client_addr.sin6_addr),buffer, sockaddr_len),ntohs(client_addr.sin6_port));

4.4 recvfrom 使用细节.

 IPV4中,recvfrom 中的fromlen参数是一个地址,在IPV4,这个值不需要设初值即可正常运行.而IPV6中,必须设好 *fromlen = sizeof(struct sockaddr_in6),否则recvfrom 在IPV6中会进行无限等待.

 

 

附件是用IPV6,实现的 TCP ECHO 和UDP ECHO样例,还在在IPV6网络实例抓包。可以大家参考一下。

 

文件: ipv6.zip
大小: 5KB
下载: 下载

转自:http://blog.chinaunix.net/u3/105675/showart_2133327.html

阅读(2143) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~