0

最近,我在解决时遇到了一个问题NSNetService

我发布了一个NSNetServicewith type _http._tcp.,就像一个 http 服务器。否则,在另一台设备上,我开始搜索此服务,它会找到它。

找到后,我就申请resolveWithTimeout了。

在解决时,有时我只得到 ipv6,我无法NSURLConnection sendAsynchronousRequest: queue: completionHandler:在其上使用 HTTPRequest。

我如何申请并且 url 上的 HTTPRequest 包含 ipv6 ?我该如何处理这个问题?

4

2 回答 2

3

看起来您正在http://{IP}:{port}/根据NSNetService. 它适用于 IPv4 地址,生成的字符串类似于http://192.168.1.8:8080/.

但是,IPv6 地址使用冒号作为分隔符(而不是句点),因此相同的代码会生成类似 的字符串http://fe80::e31:db5a:0089:98ba:8080/,并且生成的地址不正确。首先,您需要将地址用方括号括起来:http://[fe80::e31:db5a:0089:98ba]:8080/. 其次,fe80::/64(如示例中)地址是本地链接的,并且可以分配给每个支持 IPv6 的接口,因此您还需要提供要使用的接口,例如http://[fe80::e31:db5a:0089:98ba%25en0]:8080/where%25是编码的百分比符号,en0是要使用的接口名称。

综上所述,您需要为 IPv4 和 IPv6 地址构建不同的字符串。说到这,有苹果的建议:

通常,您不应该将服务解析为 IP 地址和端口号,除非您正在做一些非常不寻常的事情。–通过 IP 地址连接到 Bonjour 服务

如果可能,请尝试使用此 URL 字符串:http://{hostname}:{port}/,您将不需要那些额外的 IP 地址操作。

于 2015-04-23T16:39:05.453 回答
0

所以这就是我最终使用的......它正确地将地址转换为包括接口在内的 URL:

NSString *          result = nil;
char                host[NI_MAXHOST];
char                service[NI_MAXSERV];
int                 err;

err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
if (err == 0) {
    struct sockaddr_storage *sockaddr = (struct sockaddr_storage *)address.bytes;
    if (sockaddr->ss_family == AF_INET6) {
        result = [NSString stringWithFormat:@"[%s]:%s", host, service];
    } else if (sockaddr->ss_family == AF_INET) {
        result = [NSString stringWithFormat:@"%s:%s", host, service];
    }
}
于 2017-11-04T01:02:28.327 回答