IP-адрес от NSData с использованием Bonjour NSNetService в MonoTouch?

Я использую Xamarin + MonoTouch на iOS для поиска веб-сервера в сети, с которого я могу загружать файлы.

NSNetService, который передается в обработчик событий разрешения, содержит адреса в виде NSData. Я не могу найти хороший способ превратить эти NSData в фактический IP-адрес, из которого я могу затем создать URL-адрес, то есть http:// /folder/file.htm

Это мой обработчик событий NSNetService.AddressResolved:

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?
}

Как правильно получить IP-адрес службы от NSNetService в событии разрешения?

1 ответ

Решение

NSNetService.Addresses собственность дает вам NSData случаи, которые должны быть преобразованы в то, что IPAddress (или другие типы.NET) могут переварить. Например

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

Обратите внимание, что это может вернуть вам адрес IPv6 (или формат, который IPAddress не приму) Возможно, вы захотите перебрать все Addresses найти лучшего.

Я рассмотрю возможность добавления удобного метода в будущие версии Xamarin.iOS.

ОБНОВИТЬ

Более полная версия, которая возвращает IPAddress, будет выглядеть так:

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;
}
Другие вопросы по тегам