检查IP是否在LAN中(防火墙和路由器后面)

时间:2011-08-29 15:32:05

标签: c# networking network-programming ip lan

我现在已经在网上爬了大约5个小时,但找不到解决我问题的方法:

我的公司正在开发一款教育游戏,我正在使用Monotorrent为它编写一个autoupdater。该游戏将在学校中使用,但由于大多数学校只有非常弱的互联网连接,因此网络中只应有一台从httpseeder下载的计算机,而其他计算机应从从httpseed下载的一台计算机中获取。 / p>

所以我从跟踪器中获取大量IP地址,只需要过滤掉局域网中的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
                );
        }
    }

或者类似的技术只提供路由器/交换机的信息等等。

简而言之,我想要做的是检查是否可以通过LAN访问给定的IP。

我真的很感激任何帮助,因为这个功能是剩下的最后一个:)

3 个答案:

答案 0 :(得分:17)

你可以利用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 :(得分:1)

通常可以安全地假设任何IP(如10.x.x.x(A类)或192.x.x.x(C类))位于专用局域网内。 IP Classications

答案 2 :(得分:1)

您可能使用的一件事是尝试使用多播在客户端之间进行通信。大多数防火墙和路由器都会阻止多播流量(以及最明确的ISP),这意味着如果局域网上没有其他客户端,您将无法加入多播组。一个哑开关会传递流量,一个3层交换机可能阻止它,或者可能允许它取决于配置。无论哪种方式,如果第3层交换机阻止它,你可能完全在不同的子网上,所以所有其他选项也会失败。

我想到的一个技术是SSDP(http://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol),它可以很好地满足你的目的。这样你就不需要弄清楚你是否在局域网上,只是搜索另一个正在下载的节点,如果找不到,请自行开始下载。

由于SSDP是uPnP中使用的标准,因此您可能能够找到可以使用的合适实现。