fe80 is a link-local IPv6 address. The machine to which you're connecting must have more than one network interface -- most do, e.g. Ethernet and WiFi. To fully specific an IPv6 address, the scope_id is required. This is the sin6_scope_id from:
// IPv6 AF_INET6 sockets:
struct sockaddr_in6 {
u_int16_t sin6_family; // address family, AF_INET6
u_int16_t sin6_port; // port number, Network Byte Order
u_int32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
u_int32_t sin6_scope_id; // Scope ID
};
and when combined with the address and converted to a string looks like this: fe80::e2f8:47ff:fe23:5392%eth1
When the DNS is resolved, the NSData
wrapping a sockaddr
struct includes this information. However, in your code, you are extracting the sin6_port
and sin6_addr
, then feeding them back to GCDAsyncUDPSocket
devoid of the sin6_flowinfo
(which you don't need) and the sin6_scope_id
(which in this case you do).
Use -[GCDAsyncUDPSocket connectToAddress:error:]
directly, using the NSData
you get directly from your resolve service, and you should be good to go.