本文轉自 http://www.code4app.com/forum.php?mod=viewthread&tid=8427&highlight=ipv6php
1、IPV6-Only支持是啥?html
2、Apple如何審覈支持IPV6-Only?ios
3、應用如何支持IPV6-Only?git
1. Use High-Level Networking Frameworks;2. Don’t Use IP Address Literals;3. Check Source Code for IPv6 DNS64/NAT64 Incompatibilities;4. Use System APIs to Synthesize IPv6 Addresses;3.1 NSURLConnection是否支持IPV6?github
3.2 Cocoa的URL Loading System從iOS哪一個版本開始支持IPV6?服務器
3.3 Reachability是否須要修改支持IPV6?網絡
1
2
3
|
在Pods:Reachability中
AF_INET Files:Reachability.m
struct
sockaddr_in Files:Reachability.h , Reachability.m
|
1
2
3
4
5
6
7
|
+ (instancetype)reachabilityForInternetConnection {
struct
sockaddr_in zeroAddress;
bzero(&zeroAddress,
sizeof
(zeroAddress));
zeroAddress.sin_len =
sizeof
(zeroAddress);
zeroAddress.sin_family = AF_INET;
return
[
self
reachabilityWithAddress: (
const
struct
sockaddr *) &zeroAddress];
}
|
4、底層的socket API如何同時支持IPV4和IPV6?數據結構
4.1 IP地址從二進制到符號的轉化app
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//for IPV6
+(
NSString
*)formatIPV6Address:(
struct
in6_addr)ipv6Addr{
NSString
*address =
nil
;
char
dstStr[INET6_ADDRSTRLEN];
char
srcStr[INET6_ADDRSTRLEN];
memcpy(srcStr, &ipv6Addr,
sizeof
(
struct
in6_addr));
if
(inet_ntop(AF_INET6, srcStr, dstStr, INET6_ADDRSTRLEN) !=
NULL
){
address = [
NSString
stringWithUTF8String:dstStr];
}
return
address;
}
//for IPV4
+(
NSString
*)formatIPV4Address:(
struct
in_addr)ipv4Addr{
NSString
*address =
nil
;
char
dstStr[INET_ADDRSTRLEN];
char
srcStr[INET_ADDRSTRLEN];
memcpy(srcStr, &ipv4Addr,
sizeof
(
struct
in_addr));
if
(inet_ntop(AF_INET, srcStr, dstStr, INET_ADDRSTRLEN) !=
NULL
){
address = [
NSString
stringWithUTF8String:dstStr];
}
return
address;
}
|
4.2 本機IP獲取支持IPV6socket
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
+ (
NSString
*)deviceIPAdress
{
while
(temp_addr !=
NULL
) {
NSLog
(
@"ifa_name===%@"
,[
NSString
stringWithUTF8String:temp_addr->ifa_name]);
// Check if interface is en0 which is the wifi connection on the iPhone
if
([[
NSString
stringWithUTF8String:temp_addr->ifa_name] isEqualToString:
@"en0"
] || [[
NSString
stringWithUTF8String:temp_addr->ifa_name] isEqualToString:
@"pdp_ip0"
])
{
//若是是IPV4地址,直接轉化
if
(temp_addr->ifa_addr->sa_family == AF_INET){
// Get NSString from C String
address = [
self
formatIPV4Address:((
struct
sockaddr_in *)temp_addr->ifa_addr)->sin_addr];
}
//若是是IPV6地址
else
if
(temp_addr->ifa_addr->sa_family == AF_INET6){
address = [
self
formatIPV6Address:((
struct
sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr];
if
(address && ![address isEqualToString:
@""
] && ![address.uppercaseString hasPrefix:
@"FE80"
])
break
;
}
}
temp_addr = temp_addr->ifa_next;
}
}
}
|
4.3 設備網關地址獲取獲取支持IPV6
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/* net.route.0.inet.flags.gateway */
int
mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_FLAGS, RTF_GATEWAY};
if
(sysctl(mib,
sizeof
(mib) /
sizeof
(
int
), buf, &l, 0, 0) < 0) {
address =
@"192.168.0.1"
;
}
....
//for IPV4
for
(i = 0; i < RTAX_MAX; i++) {
if
(rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (
struct
sockaddr *)((
char
*)sa + ROUNDUP(sa->sa_len));
}
else
{
sa_tab[i] =
NULL
;
}
}
//for IPV6
for
(i = 0; i < RTAX_MAX; i++) {
if
(rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (
struct
sockaddr_in6 *)((
char
*)sa + sa->sin6_len);
}
else
{
sa_tab[i] =
NULL
;
}
}
|
4.4 設備DNS地址獲取支持IPV6
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
+(
NSArray
*)outPutDNSServers{
res_state res = malloc(
sizeof
(
struct
__res_state));
int
result = res_ninit(res);
NSMutableArray
*servers = [[
NSMutableArray
alloc] init];
if
(result == 0) {
union
res_9_sockaddr_union *addr_union = malloc(res->nscount *
sizeof
(
union
res_9_sockaddr_union));
res_getservers(res, addr_union, res->nscount);
for
(
int
i = 0; i < res->nscount; i++) {
if
(addr_union[i].sin.sin_family == AF_INET) {
char
ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(addr_union[i].sin.sin_addr), ip, INET_ADDRSTRLEN);
NSString
*dnsIP = [
NSString
stringWithUTF8String:ip];
[servers addObject:dnsIP];
NSLog
(
@"IPv4 DNS IP: %@"
, dnsIP);
}
else
if
(addr_union[i].sin6.sin6_family == AF_INET6) {
char
ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &(addr_union[i].sin6.sin6_addr), ip, INET6_ADDRSTRLEN);
NSString
*dnsIP = [
NSString
stringWithUTF8String:ip];
[servers addObject:dnsIP];
NSLog
(
@"IPv6 DNS IP: %@"
, dnsIP);
}
else
{
NSLog
(
@"Undefined family."
);
}
}
}
res_nclose(res);
free(res);
return
[
NSArray
arrayWithArray:servers];
}
|
4.4 域名DNS地址獲取支持IPV6
1
2
3
4
5
|
//ipv4
phot = gethostbyname(hostN);
//ipv6
phot = gethostbyname2(hostN, AF_INET6);
|
4.5 ping方案支持IPV6
4.6 traceRoute方案支持IPV6
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
//構造通用的IP地址結構stuck sockaddr
NSString
*ipAddr0 = [serverDNSs objectAtIndex:0];
//設置server主機的套接口地址
NSData
*addrData =
nil
;
BOOL
isIPV6 =
NO
;
if
([ipAddr0 rangeOfString:
@":"
].location ==
NSNotFound
) {
isIPV6 =
NO
;
struct
sockaddr_in nativeAddr4;
memset(&nativeAddr4, 0,
sizeof
(nativeAddr4));
nativeAddr4.sin_len =
sizeof
(nativeAddr4);
nativeAddr4.sin_family = AF_INET;
nativeAddr4.sin_port = htons(udpPort);
inet_pton(AF_INET, ipAddr0.UTF8String, &nativeAddr4.sin_addr.s_addr);
addrData = [
NSData
dataWithBytes:&nativeAddr4 length:
sizeof
(nativeAddr4)];
}
else
{
isIPV6 =
YES
;
struct
sockaddr_in6 nativeAddr6;
memset(&nativeAddr6, 0,
sizeof
(nativeAddr6));
nativeAddr6.sin6_len =
sizeof
(nativeAddr6);
nativeAddr6.sin6_family = AF_INET6;
nativeAddr6.sin6_port = htons(udpPort);
inet_pton(AF_INET6, ipAddr0.UTF8String, &nativeAddr6.sin6_addr);
addrData = [
NSData
dataWithBytes:&nativeAddr6 length:
sizeof
(nativeAddr6)];
}
struct
sockaddr *destination;
destination = (
struct
sockaddr *)[addrData bytes];
//建立socket
if
((recv_sock = socket(destination->sa_family, SOCK_DGRAM, isIPV6?IPPROTO_ICMPV6:IPPROTO_ICMP)) < 0)
if
((send_sock = socket(destination->sa_family, SOCK_DGRAM, 0)) < 0)
//設置sender 套接字的ttl
if
((isIPV6?
setsockopt(send_sock,IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,
sizeof
(ttl)):
setsockopt(send_sock, IPPROTO_IP, IP_TTL, &ttl,
sizeof
(ttl))) < 0)
//發送成功返回值等於發送消息的長度
ssize_t sentLen = sendto(send_sock, cmsg,
sizeof
(cmsg), 0,
(
struct
sockaddr *)destination,
isIPV6?
sizeof
(
struct
sockaddr_in6):
sizeof
(
struct
sockaddr_in));
|