Question

I'm using Xamarin + MonoTouch on iOS to browse for a web server on the network that I can then download files from.

The NSNetService that is passed into the resolve event handler contains addresses as NSData. I can't find a good way to turn that NSData into an actual IP address that I can then build a URL from, i.e. http:// < IPAddress > /folder/file.htm

This is my NSNetService.AddressResolved event handler:

private void OnServiceResolved(object sender, EventArgs args)
{
        NSNetService service = (NSNetService)sender;
        // service.Port is valid.
        // service.HostName is valid.
        // but we want the IP addres, which is in service.Addresses.
        // None of the following four methods works quite right.
        IPAddress address = (IPAddress)service.Addresses [0]; // Cannot convert type NSData to IPAddress
        SocketAddress address2 = (SocketAddress)service.Addresses[0]; // Cannot convert NSData to SocketAddress. A binary copy might work?
        IPHostEntry entry = (IPHostEntry)service.Addresses [0]; // Cannot convert NSData to IPHostEntry
        IPHostEntry entry2 = Dns.GetHostByName (service.HostName); // This kinda works, but is dumb. Didn't we just resolve?
}

What's the right way to get the IP address of the service from an NSNetService in a resolve event?

Was it helpful?

Solution

The NSNetService.Addresses property gives you NSData instances which must be converted into something that IPAddress (or other .NET types) can digest. E.g.

MemoryStream ms = new MemoryStream ();
(ns.Addresses [0] as NSData).AsStream ().CopyTo (ms);
IPAddress ip = new IPAddress (ms.ToArray ());

Note that this can return you an IPv6 address (or format that IPAddress won't accept). You might want to iterate all the Addresses to find the best one.

I'll look into adding a convenience method into future versions of Xamarin.iOS.

UPDATE

A more complete version, that returns an IPAddress, would look like:

static IPAddress CreateFrom (NSData data)
{
    byte[] address = null;
    using (MemoryStream ms = new MemoryStream ()) {
        data.AsStream ().CopyTo (ms);
        address = ms.ToArray ();
    }
    SocketAddress sa = new SocketAddress (AddressFamily.InterNetwork, address.Length);
    // do not overwrite the AddressFamily we provided
    for (int i = 2; i < address.Length; i++)
        sa [i] = address [i];
    IPEndPoint ep = new IPEndPoint (IPAddress.Any, 0);
    return (ep.Create (sa) as IPEndPoint).Address;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top