Проверка IP-адреса - PullRequest
       73

Проверка IP-адреса

14 голосов
/ 23 февраля 2011

Я выполняю рефакторинг своего кода и хотел использовать метод IPAddress.TryParse, чтобы проверить, является ли строка действительным адресом IPv4 вместо использования регулярных выражений:

public static bool IsIPv4(string value)
{
    IPAddress address;

    if (IPAddress.TryParse(value, out address))
    {
        if (address.AddressFamily == AddressFamily.InterNetwork)
        {
            return true;
        }
    }

    return false;
}

Мой модульный тест теперь не проходит, потому что эти входные значения возвращают true и анализируются для следующих IPAddress объектов:

value = "0.0.0.0"      ->  address = {0.0.0.0}
value = "255.255.255"  ->  address = {255.255.0.255}
value = "65536"        ->  address = {0.1.0.0}

Имеет ли это смысл? Я вижу, что 0.0.0.0 технически является действительным адресом IPv4, даже если пользователю нет смысла вводить его. Как насчет двух других? Почему они конвертированы в том виде, в каком они есть, и я должен считать их действительными, даже если это может быть непрозрачно для пользователя, который, возможно, просто забыл ввести точки (65536 вместо 6.5.5.36).

Любая помощь наиболее ценится.

Ответы [ 10 ]

21 голосов
/ 24 февраля 2011

Задача IPAddress.TryParse () - не проверять, является ли строка действительным IP-адресом, но может ли содержимое строки быть проанализировано (т.е. ; преобразован) в действительный IP-адрес.

Все параметры в ваших тестовых примерах могут быть фактически проанализированы для представления и IP. То, что сводится к тому, что ваши тесты являются действительными. Проблема заключается в том, что данные для ваших тестовых случаев недействительны или вы не используете правильный инструмент (ы) в своем тестовом примере для получения ожидаемого результата.

Если вы специально тестируете действительный IPv4 с ровно 4 квадраторами (каждое из которых является целым числом от 0 до 255) и хотите избежать регулярного выражения, то вместо этого вы могли бы разделить, а затем проанализировать и проверить.

    public static bool IsIPv4(string value)
    {
        var quads = value.Split('.');

        // if we do not have 4 quads, return false
        if (!(quads.Length==4)) return false;

        // for each quad
        foreach(var quad in quads) 
        {
            int q;
            // if parse fails 
            // or length of parsed int != length of quad string (i.e.; '1' vs '001')
            // or parsed int < 0
            // or parsed int > 255
            // return false
            if (!Int32.TryParse(quad, out q) 
                || !q.ToString().Length.Equals(quad.Length) 
                || q < 0 
                || q > 255) { return false; }

        }

        return true;
    }
9 голосов
/ 23 февраля 2011

Похоже, документы для IPAddress.Parse рационализируют это поведение, указав, что ввод меньшего числа частей удобен для ввода адресов классов A и B.Если вы хотите форсировать адрес из четырех частей, вы, возможно, просто захотите проверить, что в адресе есть три периода, прежде чем вводить его в IPAddress.TryParse, я полагаю.

Некоторый код для вашей справки:

// verify that IP consists of 4 parts
if (value.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Length == 4)
{
    IPAddress ipAddr;
    if (IPAddress.TryParse(value, out ipAddr))
    {
        // IP is valid
    }
    else
        // invalid IP
}
else
    // invalid IP
6 голосов
/ 23 февраля 2011

Если вы хотите быть очень строгими в отношении вашего ввода, то вы можете сравнить ToString() версию проанализированного IPAddress и отклонить ввод, если они отличаются.

Адрес с нулевым адресоми другие подобные вещи должны рассматриваться как особые случаи.

5 голосов
/ 18 октября 2012

Я предлагаю:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }
4 голосов
/ 20 января 2014
    public static bool IsIPv4(string ipAddress)
    {
        return Regex.IsMatch(ipAddress, @"^\d{1,3}(\.\d{1,3}){3}$") &&
            ipAddress.Split('.').SingleOrDefault(s => int.Parse(s) > 255) == null;
    }

Другие ответы либо разрешают IPv6, либо разрешают ввод, например «1.-0.1.1».

2 голосов
/ 23 февраля 2011

Количество частей (каждая часть разделена точкой) в ipString определяет способ построения IP-адреса.Адрес, состоящий из одной части, хранится непосредственно в сетевом адресе.Адрес из двух частей, удобный для указания адреса класса A, помещает ведущую часть в первый байт, а завершающую часть - в самые правые три байта сетевого адреса.Адрес из трех частей, удобный для указания адреса класса B, помещает первую часть в первый байт, вторую часть во второй байт и последнюю часть в самые правые два байта сетевого адреса.Например:

Количество деталей и пример IPv4-адреса ipString для IP-адреса

1 - «65536» 0.0.255.255

2 - «20.2» 20.0.0.2

2 - "20.65535" 20.0.255.255

3 - "128.1.2" 128.1.0.2

Возможно, вы захотите обратиться к документации MSDN http://msdn.microsoft.com/en-us/library/system.net.ipaddress.parse.aspx

Лучшей ставкой будет IPAddress.ToString () или регулярные выражения.

1 голос
/ 02 сентября 2013

Несмотря на то, что на этот вопрос ответили, как два года назад, я думаю, что уместно поднять то, что я выяснил, когда искал то же самое сегодня, и, найдя эту страницу, решил, что я слишком ленив, чтобы пройти через все проверка программно.

Если информация принимается через Form и TextBox, было бы в ваших интересах использовать MaskedTextBox вместо этого. Вы можете заставить пользователя вводить информацию в формате IP-адреса, вместо того, чтобы делать догадки самостоятельно.

Маска, которая будет использоваться для такой проверки: 990.990.990.990, которая говорит OptionalNumber, OptionalNumber, MandatoryNumber, потому что 1.1.1.1, 10.10.10.10 и 123.123.123.123 - все допустимые форматы IP-адреса. Маски имеют тот же формат, что Microsoft использует в Access.

1 голос
/ 23 февраля 2011

Да, это действительные адреса.См. http://en.wikipedia.org/wiki/IPv4#Address_representations для получения дополнительной информации.

0 голосов
/ 13 марта 2014

В приведенном ниже коде используется регулярное выражение, предложенное Roshe

        string txt = textBox1.Text;

        string ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9‌​]{2}|2[0-4][0-9]|25[0-5])$";    // IP validation 

        Regex r = new Regex(ValidIpAddressRegex, RegexOptions.IgnoreCase | RegexOptions.Singleline);
        Match m = r.Match(txt);

        if (!m.Success)
        {
          //Not a valid IP
        }

        else
        {


          //A valid IP

        }
0 голосов
/ 23 февраля 2011

Это имеет смысл, так как 65536 равно 0x00010000 или 0.1.0.0. Я предполагаю, что TryParse также примет шестнадцатеричные числа. В любом случае, я не думаю, что вы захотите принять такое значение от обычного пользователя, но я полагаю, что это зависит от конечного пользователя.

...