0

IPアドレスが特定の範囲内にあるかどうかを確認したいのですが、一致する"*"だけです。たとえば、「202.121.189.8」は「202.121.189」にあり*ます。

シナリオでは、禁止されているIPのリストがあり、そのうちのいくつかにはが含まれている"*"ため、関数を作成しました。これまでのところ正常に機能しています。

static bool IsInRange(string ip, List<string> ipList)
{
    if (ipList.Contains(ip))
    {
        return true;
    }

    var ipSets = ip.Split('.');
    foreach (var item in ipList)
    {
        var itemSets = item.Split('.');
        for (int i = 0; i < 4; i++)
        {
            if (itemSets[i] == "*")
            {
                bool isMatch = true;
                for (int j = 0; j < i; j++)
                {
                    if (ipSets[i - j - 1] != itemSets[i - j - 1])
                    {
                        isMatch = false;
                    }
                }
                if (isMatch)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

テストコード:

string ip = "202.121.189.8";
List<string> ipList = new List<string>() { "202.121.168.25", "202.121.189.*" };

Console.WriteLine(IsInRange(ip, ipList));

しかし、私が書いたものは非常にばかげていると思います、そして私はそれを最適化したいです、誰かがこの機能を単純化する方法を知っていますか?「for....if...」をあまり使用しないでください。

4

4 に答える 4

1

禁止されているサブネットを、マスク+ベースアドレスのペアの形式で表すことをお勧めします。したがって、チェックは次のようになります。

banned = (ip & mask == baseaddress & mask);

11.22.33。*の場合、ベースアドレスは11*0x1000000 + 22*0x10000 + 33*0x100、マスクは0xffffff00になります。

単一アドレス55.44.33.22の場合、アドレスは55*0x1000000 + 44*0x10000 * 33*0x100 + 22、マスクは0xffffffffになります。

別の手順として、アドレスを32ビット整数に変換する必要があります。

結局のところ、コードは次のようになります。

int numip = ip2int(ip);
bool isIpBanned = banList.Any(item =>
            numip & item.mask == item.baseaddress & item.mask);

ちなみに、この方法では、小さなサブセットの禁止さえも表すことができます。

int ip2int(string ip) // error checking omitted
{
    var parts = ip.Split('.');
    int result = 0;
    foreach (var p in parts)
        result = result * 0x100 + int.Parse(p);
}


class BanItem { public int baseaddres; public int mask; }

BanItem ip2banItem(string ip)
{
    BanItem bi = new BanItem() { baseaddres = 0, mask = 0 };
    var parts = ip.Split('.');
    foreach (var p in parts)
    {
        bi.baseaddress *= 0x100;
        bi.mask *= 0x100;
        if (p != "*")
        {
            bi.mask += 0xff;
            bi.baseaddress += int.Parse(p);
        }
    }
    return bi;
}

banList = banIps.Select(ip2banItem).ToList();
于 2012-07-23T12:32:43.710 に答える
1

*のあるIPとアスタリスクのないIPの別々のリストを保持する必要があると思います。

IpList1に*となしのIPが含まれていると言う

IpList2---これらに含まれるもの*..実際に保存するのは、このリストの。*の前の部分です。たとえば、202.121.189。*は202.121.189としてのみ保存されます。

したがって、特定のIPアドレスについては、IpList1でそのIPアドレスを確認する必要があります。そこに見つからない場合は、IPList 2の各Ipについて、入力IPのサブストリングであるかどうかを確認する必要があります。

したがって、複雑なforループとifループは必要ありません。

于 2012-07-23T12:39:51.430 に答える
0

Javaで書かれた(テストされていない):

static boolean IsInRange(String ip, Vector<String> ipList) {
    int indexOfStar = 0;
    for (int i=0; i<ipList.size(); i++) {
        if (ipList.contains("*")) {
            indexOfStar = ipList.indexOf("*");
            if ((ip.substring(0, indexOfStar)).equals(ipList.get(i).substring(0, indexOfStar))) {
                return true;
            }
        }
    }
    return false;
}
于 2012-07-23T12:44:31.983 に答える
0

xkcdコミックのように空間充填曲線を使用します:http://xkcd.com/195/。これは関数H(x、y)=(H(x)、H(y))であり、2次元を1次元に縮小します。また、あなたが本物のb***コーダーであることも示します。

于 2012-07-23T12:55:17.977 に答える