本文转自 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));
|