Search code examples
iosobjective-cxcodexcode6.1ios8.1

NSNetService Resolve ipv6 that can not make an http request on it


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 ?


Solution

  • 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.