这是苹果的关于ipv6改造的官方文档
https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW1
简单整理了一下客户端的改动点。
A DNS64/NAT64 network is an IPv6-only network
DNS64 / NAT64网络是仅IPv6的网络
If you’re writing a client-side app using high-level networking APIs such as NSURLSession
and the CFNetwork frameworks and you connect by name, you should not need to change anything for your app to work with IPv6 addresses. If you aren’t connecting by name, you probably should be.
如果您使用诸如NSURLSession和
和CFNetwork框架之类的高级网络API编写客户端应用程序,并且通过域名进行连接,则无需为应用程序使用IPv6地址而进行任何更改。如果您未按域名进行连接,则应该如此。
在这种类型的工作流中,客户端将DNS查询发送到DNS64服务器,该服务器从DNS服务器请求IPv6地址。找到IPv6地址后,它会立即传递回客户端。但是,当找不到IPv6地址时,DNS64服务器将改为请求IPv4地址。然后,DNS64服务器通过为IPv4地址添加前缀来合成IPv6地址,并将其传递回客户端。在这方面,客户端始终会收到一个支持IPv6的地址。
常见问题:
WebKit.
Cocoa URL loading system. NSURLSession
, NSURLRequest
, and NSURLConnection
CFNetwork. 打开主机的一对TCP套接字,请调用CFStreamCreatePairWithSocketToCFHost
方法
不要用如getaddrinfo
和SCNetworkReachabilityCreateWithName
。而是使用高级网络框架和与地址无关的API版本(例如getaddrinfo
和)getnameinfo。
如果必须检查网络可用性,请避免调用SCNetworkReachabilityCreateWithAddress方法。调用SCNetworkReachabilityCreateWithName方法。
使用sockaddr_storage
足够大的地址存储容器(例如)来存储IPv6地址。
检查并消除特定于IPv4的API,例如:
inet_addr()
inet_aton()
inet_lnaof()
inet_makeaddr()
inet_netof()
inet_network()
inet_ntoa()
inet_ntoa_r()
bindresvport()
getipv4sourcefilter()
setipv4sourcefilter()
如果您的代码处理的是IPv4类型,请确保也处理了等效的IPv6。
IPv4 |
IPv6 |
---|---|
|
|
|
|
|
|
|
|
|
|
如果实在没有域名
请使用getaddrinfo
解析IPv4地址文字。如果当前网络接口不支持IPv4,但支持IPv6,NAT64和DNS64,则执行此任务将得到一个合成的IPv6地址。
如何使用解析IPv4文字getaddrinfo。假设您有一个以四个字节(例如{192, 0, 2, 1})存储在内存中的IPv4地址,此示例代码将其转换为字符串(例如"192.0.2.1"),用于getaddrinfo合成IPv6地址(例如struct sockaddr_in6包含IPv6地址"64:ff9b::192.0.2.1")并尝试连接到该IPv6地址。
#include
#include
#include
#include
uint8_t ipv4[4] = {192, 0, 2, 1};
struct addrinfo hints, *res, *res0;
int error, s;
const char *cause = NULL;
char ipv4_str_buf[INET_ADDRSTRLEN] = { 0 };
const char *ipv4_str = inet_ntop(AF_INET, &ipv4, ipv4_str_buf, sizeof(ipv4_str_buf));
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;
error = getaddrinfo(ipv4_str, "http", &hints, &res0);
if (error) {
errx(1, "%s", gai_strerror(error));
/*NOTREACHED*/
}
s = -1;
for (res = res0; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (s < 0) {
cause = "socket";
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
cause = "connect";
close(s);
s = -1;
continue;
}
break; /* okay we got one */
}
if (s < 0) {
err(1, "%s", cause);
/*NOTREACHED*/
}
freeaddrinfo(res0);
注意:在iOS 9.2和OS X 10.11.2中,getaddrinfo增加了合成IPv6地址的能力。但是,利用它不会破坏与旧系统版本的兼容性。