it-swarm.com.ru

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

Я рефакторинг своего кода и хотел использовать метод 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).

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

13
Martin Buberl

Похоже, документы для 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
9
mquander

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

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

Если вы специально тестируете действительный IPv4 с ровно четырьмя квадраторами (каждый из которых представляет собой целое число от 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;
    }
21
Mad Man Moon

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

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

6
Jeffrey L Whitledge

Я предлагаю:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }
5
user1756694
    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».

4
Dennis Gorelik

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

Количество деталей и пример ipString IPv4-адрес для 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 () или регулярные выражения. 

2
ukhardy

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

Если информация принимается через 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
Matt Miller

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

1
Jim Mischel

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

0
Jeff

В приведенном ниже коде используется регулярное выражение, предложенное 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
dmn