Reputation: 25
Recently, i was facing a problem while resolving NSNetService
.
I was published an NSNetService
with type _http._tcp.
, to be just like an http server.
Other wise, on another device, i was start searching for this service, and it will find it.
After finding it, i was apply resolveWithTimeout
on it.
While resolving, sometimes i was get only ipv6, that i can't make an HTTPRequest using NSURLConnection sendAsynchronousRequest: queue: completionHandler:
on it.
How can i apply and HTTPRequest on url contains ipv6 ? How can i deal with that problem ?
Upvotes: 0
Views: 1088
Reputation: 2770
So this is what I end up using... it correctly translates address into URL including the interface:
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];
}
}
Upvotes: 0
Reputation: 316
It looks like you're building a string like http://{IP}:{port}/
based on the information provided in NSNetService
. And it works fine for an IPv4 address, the resulting string is like http://192.168.1.8:8080/
.
However, IPv6 addresses use colons as a separator (instead of periods), so the same code generates a string like http://fe80::e31:db5a:0089:98ba:8080/
, and the resulting address is incorrect. First, you need to wrap the address in square brackets: http://[fe80::e31:db5a:0089:98ba]:8080/
. Second, fe80::/64
(as in the example) addresses are link-local and can be assigned to each IPv6-supporting interface, so you need to also provide the interface to use, e.g. http://[fe80::e31:db5a:0089:98ba%25en0]:8080/
where %25
is an encoded percent symbol and en0
is the interface name to use.
To sum up, you need to build different strings for IPv4 and IPv6 addresses. Speaking of which, there are Apple's recommendations:
As a rule, you should not resolve a service to an IP address and port number unless you are doing something very unusual. – Connecting to a Bonjour Service by IP Address
Try to use this URL string if possible: http://{hostname}:{port}/
, you won't need those extra IP address manipulations.
Upvotes: 4