Подтвердить что ты не робот

Проверка 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;
}

Мой unit test теперь терпит неудачу, потому что эти входные значения возвращают 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).

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

4b9b3361

Ответ 1

Похоже, что документы для IPAddress.Parse рационализируют это поведение, указывая, что ввод меньшего количества деталей удобен для ввода адресов класса А и В, Если вы хотите принудительно ввести адрес из четырех частей, вы можете просто проверить, что есть три периода в адресе, прежде чем подавать его на 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

Ответ 2

Задача 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;
    }

Ответ 3

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

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

Ответ 4

Я предлагаю:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }

Ответ 5

    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".

Ответ 6

Количество частей (каждая часть разделяется на период) в ipString определяет, как создается IP-адрес. Адрес одной части хранится непосредственно в сетевом адресе. Адрес из двух частей, удобный для указания адреса класса А, помещает ведущую часть в первый байт и конечную часть в три три байта сетевого адреса. Адрес из трех частей, удобный для указания адреса класса 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() или регулярные выражения.

Ответ 8

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

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

Ответ 9

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

Ответ 10

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

        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

        }