Проверьте, есть ли IP в локальной сети (за брандмауэрами и маршрутизаторами) - PullRequest
11 голосов
/ 29 августа 2011

Я ползу в Интернете около 5 часов и не могу найти решение своей проблемы:

Моя компания разрабатывает обучающую игру, и я пишу автообновление для нее, используя Monotorrent. Игра будет использоваться в школах, но, поскольку большинство школ имеют очень слабое интернет-соединение, в сети должен быть только один компьютер, который загружается с httpseeder, а остальные должны просачиваться с одного компьютера, который загружается с httpseed.

Итак, я получаю множество IP-адресов от трекера и мне нужно отфильтровать только те, которые есть в локальной сети.

Конечно, школы иногда довольно строги с брандмауэрами, и в некоторых школах будет множество маршрутизаторов и коммутаторов.

Я уже попробовал большинство решений, например

 NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();

    foreach (NetworkInterface iface in interfaces)
    {
        IPInterfaceProperties properties = iface.GetIPProperties();

        foreach (UnicastIPAddressInformation address in properties.UnicastAddresses)
        {
            Console.WriteLine(
                "{0} (Mask: {1})",
                address.Address,
                address.IPv4Mask
                );
        }
    }

Или аналогичные методы предоставляют только информацию о маршрутизаторе / коммутаторе / чем-либо еще.

Итак, вкратце, я хочу проверить, доступен ли данный IP через LAN.

Я бы очень признателен за любую помощь, потому что эта функция является последней из оставшихся:)

Ответы [ 3 ]

17 голосов
/ 29 августа 2011

Вы можете воспользоваться TTL.Если TTL равен 1, пакет не сможет попасть в Интернет:

private static bool IsLanIP(IPAddress address)
{
    var ping = new Ping();
    var rep = ping.Send(address, 100, new byte[] { 1 }, new PingOptions()
    {
        DontFragment = true,
        Ttl = 1
    });
    return rep.Status != IPStatus.TtlExpired && rep.Status != IPStatus.TimedOut && rep.Status != IPStatus.TimeExceeded;
}

Однако помните, что по какой-то причине он называется маской IPv4 - вы можете использовать ее как единоевот ваше алгоритмическое решение):

private static bool IsLanIP(IPAddress address)
{
    var interfaces = NetworkInterface.GetAllNetworkInterfaces();
    foreach (var iface in interfaces)
    {
        var properties = iface.GetIPProperties();
        foreach (var ifAddr in properties.UnicastAddresses)
        {
            if (ifAddr.IPv4Mask != null && 
                ifAddr.Address.AddressFamily == AddressFamily.InterNetwork &&
                CheckMask(ifAddr.Address, ifAddr.IPv4Mask, address))
                return true;
        }
    }
    return false;
}

private static bool CheckMask(IPAddress address, IPAddress mask, IPAddress target)
{
    if (mask == null)
        return false;

    var ba = address.GetAddressBytes();
    var bm = mask.GetAddressBytes();
    var bb = target.GetAddressBytes();

    if (ba.Length != bm.Length || bm.Length != bb.Length)
        return false;

    for (var i = 0; i < ba.Length; i++)
    {
        int m = bm[i];

        int a = ba[i] & m;
        int b = bb[i] & m;

        if (a != b)
            return false;
    }

    return true;
}
1 голос
/ 30 августа 2011

Одна вещь, которую вы могли бы использовать, это попытаться установить связь между клиентами с помощью многоадресной рассылки. Большинство брандмауэров и маршрутизаторов блокируют многоадресный трафик (и, наиболее определенно, интернет-провайдеров), что означает, что вы не сможете присоединиться к многоадресной группе, если в сети нет другого клиента. Тупой коммутатор будет передавать трафик, коммутатор уровня 3 может заблокировать его или разрешить его в зависимости от конфигурации. В любом случае, если коммутатор уровня 3 блокирует его, вы, вероятно, в любом случае находитесь в разных подсетях, поэтому все остальные параметры также будут неудачными.

Одна технология, которая приходит на ум, - это SSDP (http://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), которая, я полагаю, вполне удовлетворит вашу цель. Таким образом, вам не нужно выяснять, находитесь ли вы в локальной сети или нет, просто найдите другой узел, который активно загружается, если вы не можете его найти, начните загружать себя.

Поскольку SSDP - это стандарт, используемый в uPnP, вы, вероятно, сможете найти достойные реализации, с которыми можно работать.

1 голос
/ 29 августа 2011

Обычно любые IP-адреса, такие как 10.x.x.x (класс A) или 192.x.x.x (класс C), можно смело считать находящимися внутри частной локальной сети. IP-классификация

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...