2

我正在用 Java 编写一个小的 API 程序,它将验证 IP 地址。在最简单的迭代中(1.2.3.4),我只是调用像 googles guava 这样的库并得到真或假。

我遇到的问题是输入可以包含ip范围,即192-198.10.12.16-20/24

由于 guava 不会将这种输入验证为有效的 IP 地址,因此我试图在调用 guava 之前处理 IP 地址。

我想我会做以下事情:

  1. 如果有,请切断网络掩码(此处为 /24)。
  2. 使用 split("\.") 方法将八位字节分成字符串数组(?)。
  3. 将八位字节的 IP 范围提取到一个单独的字符串数组中,因此八位字节数组仅包含主 IP 地址,我现在可以将其传递给 guava 进行验证。
  4. 作为最后一步,我将检查给定的 IP 范围是否大于它所属的八位字节并且小于 256。如果是,那么原始 IP 地址(见上文)就可以了。

如前所述,我需要一种数据类型,允许我存储主 IP 地址的八位字节和八位字节的 IP 范围(如果有)之间的原始关系,以便执行 4 中描述的检查并恢复原始 IP 地址表示法,即能够连接八位字节和 IP 范围。

为了可视化上述内容,我需要:

Octet 1 (192), IP Range 1 (198)
Octet 2 (10), IP Range 2 ()
Octet 3 (12), IP Range 3()
Octet 4 (16), IP Range 4 (20)

像八位字节这样的数组会String [][]完成这项工作吗?如果是,我将如何填写?如果不是,还有什么其他数据类型适合这里?

4

3 回答 3

2

我建议使用一个自定义对象——一个可以在这里处理不同可能性的对象。

它会更加清晰和简单。最重要的是,它可以具有处理不同情况的方法(例如,它可以具有一个迭代器,该迭代器将返回 IP 地址对象所涵盖的任何范围。

配对只是一个坏主意(可读性),我只是建议找到更具表现力的东西。

于 2013-04-09T22:21:04.170 回答
1

比尔 K 是对的。这是一个简单的示例类:

    public class IPAddress {

        private IPOctet octet1;
        private IPOctet octet2;
        private IPOctet octet3;
        private IPOctet octet4;

        private static final String NETWORK_MASK_CHAR = "/24";

        public IPAddress(String value) throws Exception{
            value = cutOffNetworkMask(value);
            String[] octets = value.split("\\.");
            if (octets.length < 4) throw new Exception("Invalid input value. Too few octets.");
            octet1 = new IPOctet(octets[0]);
            octet2 = new IPOctet(octets[1]);
            octet3 = new IPOctet(octets[2]);
            octet4 = new IPOctet(octets[3]);
        }

        public boolean hasMatchOf(IPAddress another){
            if (!octet1.isMatching(another.getOctet1())) return false;
            if (!octet2.isMatching(another.getOctet2())) return false;
            if (!octet3.isMatching(another.getOctet3())) return false;
            if (!octet4.isMatching(another.getOctet4())) return false;
            return true;
        }

        public IPOctet getOctet1(){ return octet1; }
        public IPOctet getOctet2(){ return octet2; }
        public IPOctet getOctet3(){ return octet3; }
        public IPOctet getOctet4(){ return octet4; }

        private static String cutOffNetworkMask(String base){
            int index = base.indexOf(NETWORK_MASK_CHAR);
            try{
                if (index > -1) base = base.substring(0, index);
            }catch(IndexOutOfBoundsException ignored){}
            return base;
        }

    }

IPOctet 类:

    public class IPOctet {

        private static final String RANGE_SYMBOL = "-";
        int max = 255;
        int min = 0;

        public IPOctet(String stringValue) throws Exception {
            int index = stringValue.indexOf(RANGE_SYMBOL);
            if (index < 0){
                // This octet is a single byte;
                max = str2int(stringValue);
                min = max;
            }else{
                // This octet has a range.
                String[] values = stringValue.split(RANGE_SYMBOL);
                if (values.length != 2) throw new Exception("Invalid Input. Range must be like xx-xx");
                min = str2int(values[0]);
                max = str2int(values[1]);
            }
        }

        public boolean isMatching(IPOctet another) {
            if (max < another.getMinValue()) return false;
            if (min > another.getMaxValue()) return false;
            return true;
        }

        public int getMinValue(){ return min; }
        public int getMaxValue(){ return min; }

        private static int str2int(String input) throws Exception{
            int result;
            try{
                result = Integer.parseInt(input);
            }catch(NumberFormatException nfe){
                throw new Exception("Invalid input. Input is not a number.");
            }
            validate(result);
            return result;
        }

        private static void validate(int input) throws Exception{
            if (input < 0 || input > 255) throw new Exception("Invalid input. Must be between 0 and 255");
        }

    }

这里有一个简单的测试用例:

    public class Main {

        public static void main(String[] args){
            try{
                IPAddress adr1 = new IPAddress("192.168.1.0-255");
                IPAddress adr2 = new IPAddress("192.168.1.1/24");
                IPAddress adr3 = new IPAddress("1.2.3.4");
                System.out.println("adr2 matches adr1: " + adr1.hasMatchOf(adr2));
                System.out.println("adr3 matches adr1: " + adr1.hasMatchOf(adr3));
            }catch(Exception e){
                System.err.println(e.getMessage());
            }
        }
    }

有了它,现在您可以将IPAddresses 存储在 a ArrayListor中LinkedList

ArrayList<IPAddress> addresses = new ArrayList<>();
addresses.add(new IPAddress("8.8.8.8"));
addresses.add(new IPAddress("198.252.206.16"));

IPAddress mask = new IPAddress("20-200.200-255.100-255.0-255");
for (IPAddress addr : addresses){
    if (mask.hasMatchOf(addr)){
        ...
    }else{
        ..
    }
}
于 2013-04-10T00:37:38.990 回答
0

您不必为简单的工作/程序使用外部框架。使用正则表达式,您将能够简化程序并使其非常高效。检查以下链接:Regex to match Hostname or IP Address

于 2013-04-09T22:39:59.780 回答