user-0 提问: ipv6地址处理

回复:
user: user-1
content: //IPv6地址表示 //IPv6地址为128位长，但通常写作8组，每组为四个十六进制数的形式。例如： //FE80:0000:0000:0000:AAAA:0000:00C2:0002 是一个合法的IPv6地址。 //要是嫌这个地址看起来还是太长，这里还有种办法来缩减其长度，叫做零压缩法。 //如果几个连续段位的值都是0，那么这些0就可以简单的以::来表示，上述地址就可以写成 //FE80::AAAA:0000:00C2:0002。这里要注意的是只能简化连续的段位的0，其前后的0都要保留， //比如FE80的最后的这个0，不能被简化。还有这个只能用一次，在上例中的 //AAAA后面的0000就不能再次简化。当然也可以在AAAA后面使用::，这样的话前面的 //12个0就不能压缩了。这个限制的目的是为了能准确还原被压缩的0.不然就无法确定每个::代表了多少个0. //2001:0DB8:0000:0000:0000:0000:1428:0000 //2001:0DB8:0000:0000:0000::1428:0000 //2001:0DB8:0:0:0:0:1428:0000 //2001:0DB8:0::0:0:1428:0000 //2001:0DB8::1428:0000都是合法的地址，并且他们是等价的。但 //2001:0DB8::1428::是非法的。（因为这样会使得搞不清楚每个压缩中有几个全零的分组） //同时前导的零可以省略，因此： //2001:0DB8:02de::0e13等价于2001:DB8:2de::e13 #include <stdio.h> #include <string.h> char ipv60[]="2001:0DB8:0000:0000:0000:0000:1428:0000"; char ipv61[]="1040::1"; char ipv62[]="fe80::20c:29ff:fe6b:2516"; char ipv63[]="::ffff:c0a8:5909"; unsigned char ip_v6[16]; void show(char *a) {     int i;     printf("%-39s=>",a);     for (i=0;i<16;i++) printf("%02x ",ip_v6[i]);     printf("\n"); } void inet_addr6(char *a) {     char *p;     int n,i,r,k,j;     short s;     k=0;     p=a;     while (1) {         if (*p==':') k++;         p++;         if (*p==0) break;     }     if (a[0]==':') k--;     i=0;     p=a;     while (1) {         r=sscanf(p,"%hx%n",&s,&n);         if (1==r) {             ip_v6[i]=*((unsigned char *)&s+1);             ip_v6[i+1]=*((unsigned char *)(&s));             i+=2;             if (i>=16) break;             p+=n;         } else if (0==r) {             if (p[0]==':') {                 if (p[1]==':') {                     for (j=0;j<(8-k)*2;j++) ip_v6[i+j]=0;                     i+=(8-k)*2;                     if (i>=16) break;                     p+=2;                 } else {                     p++;                 }             } else {                 printf("Format Error [%s]!\n",a);             }         } else break;     } } int main() {     inet_addr6(ipv60);show(ipv60);     inet_addr6(ipv61);show(ipv61);     inet_addr6(ipv62);show(ipv62);     inet_addr6(ipv63);show(ipv63);     return 0; } //2001:0DB8:0000:0000:0000:0000:1428:0000=>20 01 0d b8 00 00 00 00 00 00 00 00 14 28 00 00 //1040::1                                =>10 40 00 00 00 00 00 00 00 00 00 00 00 00 00 01 //fe80::20c:29ff:fe6b:2516               =>fe 80 00 00 00 00 00 00 02 0c 29 ff fe 6b 25 16 //::ffff:c0a8:5909                       =>00 00 00 00 00 00 00 00 00 00 ff ff c0 a8 59 09 //

user: user-0
content: 引用 1 楼 zhao4zhong1 的回复:IPv6 addresses are not so predictable, due to the IPv6 address convention that enables the use of a double-colon (::) to represent a series of zeros. As such, the following IPv6 address representations equate to the same IPv6 address:   1040:0:0:0:0:0:0:1 1040::1  so fe80::20c:29ff:fe6b:2516 fe80:0:0:0:20c:29ff:fe6b:2516 representations equate to the same IPv6 address  so unsigned char ip_v6[16]={0xfe,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0c,0x29,0xff,0xfe,0x6b,0x25,0x16};//byte order maybe error. 是的，，但是我总不能手写到ipv6[16]里吧！

user: user-1
content: IPv6 addresses are not so predictable, due to the IPv6 address convention that enables the use of a double-colon (::) to represent a series of zeros. As such, the following IPv6 address representations equate to the same IPv6 address:   1040:0:0:0:0:0:0:1 1040::1  so fe80::20c:29ff:fe6b:2516 fe80:0:0:0:20c:29ff:fe6b:2516 representations equate to the same IPv6 address  so unsigned char ip_v6[16]={0xfe,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0c,0x29,0xff,0xfe,0x6b,0x25,0x16};//byte order maybe error.