Каков наилучший способ проверки IP-адреса?

У меня есть метод для проверки IP-адреса параметра. Будучи новым для развития в целом, я хотел бы знать, есть ли лучший способ сделать это.

/// <summary>
/// Check IP Address, will accept 0.0.0.0 as a valid IP
/// </summary>
/// <param name="strIP"></param>
/// <returns></returns>
public Boolean CheckIPValid(String strIP)
{
    //  Split string by ".", check that array length is 3
    char chrFullStop = '.';
    string[] arrOctets = strIP.Split(chrFullStop);
    if (arrOctets.Length != 4)
    {
        return false;
    }
    //  Check each substring checking that the int value is less than 255 and that is char[] length is !> 2
    Int16 MAXVALUE = 255;
    Int32 temp; // Parse returns Int32
    foreach (String strOctet in arrOctets)
    {
        if (strOctet.Length > 3)
        {
            return false;
        }

        temp = int.Parse(strOctet);
        if (temp > MAXVALUE)
        {
            return false;
        }
    }
    return true;
}

Его простой (я мог бы это сделать), но, похоже, это трюк.

Ответ 1

Ограничение с помощью метода IPAddress.TryParse заключается в том, что он проверяет, может ли строка быть преобразована в IP-адрес, поэтому, если она снабжена строковым значением типа "5", оно считает это "0.0.0.5".

Другой подход к проверке IPv4 может быть следующим:

public bool ValidateIPv4(string ipString)
{
    if (String.IsNullOrWhiteSpace(ipString))
    {
        return false;
    }

    string[] splitValues = ipString.Split('.');
    if (splitValues.Length != 4)
    {
        return false;
    }

    byte tempForParsing;

    return splitValues.All(r => byte.TryParse(r, out tempForParsing));
}

Его можно было протестировать следующим образом:

List<string> ipAddresses = new List<string>
{
    "2",
    "1.2.3",
    "1.2.3.4",
    "255.256.267.300",
    "127.0.0.1",
};
foreach (var ip in ipAddresses)
{
    Console.WriteLine($"{ip} ==> {ValidateIPv4(ip)}");
}

Выход будет:

2 ==> False
1.2.3 ==> False
1.2.3.4 ==> True
255.256.267.300 ==> False
127.0.0.1 ==> True

Вы также можете использовать IPAddress.TryParse но он имеет ограничения и может привести к некорректному разбору.

Метод System.Net.IPAddress.TryParse

Обратите внимание, что TryParse возвращает true, если он успешно разбирает вход, но это не обязательно означает, что результирующий IP-адрес является допустимым. Не используйте этот метод для проверки IP-адресов.

Но это будет работать с нормальной строкой, содержащей не менее трех точек. Что-то вроде:

string addrString = "192.168.0.1";
IPAddress address;
if (IPAddress.TryParse(addrString, out address)) {
       //Valid IP, with address containing the IP
} else {
       //Invalid IP
}

С помощью IPAddress.TryParse вы можете проверить наличие трех точек, а затем вызвать TryParse как:

public static bool ValidateIPv4(string ipString)
{
    if (ipString.Count(c => c == '.') != 3) return false;
    IPAddress address;
    return IPAddress.TryParse(ipString, out address);
}

Ответ 2

using System.Net;
public static bool CheckIPValid(string strIP)
{
    IPAddress result = null;
    return
        !String.IsNullOrEmpty(strIP) &&
        IPAddress.TryParse(strIP, out result);
}

и вы сделали

Редактировать 1

Добавлены некоторые дополнительные проверки для предотвращения исключения исключений (которые являются дорогостоящими). PS он не будет обрабатывать unicode.

Изменить 2

@StephenMurby IPAddress.TryParse вернет true, если он успешно проанализировал строку. Если вы проверите документацию по методу, хотя в двух случаях он будет генерировать исключение.

  1. Строка имеет значение NULL.
  2. Строка содержит символы Unicode.

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

Я говорю, нарушая выражение о возвращении,

  1. Строка не является нулевой (и пустой, которая не будет разбираться в любом случае) И
  2. IP-адрес правильно анализируется.

Помните, что логические выражения С# ленивы, поэтому CLR не попытается даже проанализировать строку, если она является null или пустой.

Про недостающие, если, вы можете сделать что-то вроде,

if (IP.TryParse(strIP, out result)
{
    return true;
}

Но все, что вы действительно делаете, говорит, что если что-то истинно, верните истину. Легче просто вернуть выражение сразу.

Ответ 4

Структура предоставляет класс IPAddress который, в свою очередь, предоставляет вам методы Parse и TryParse.

// myAddress is a System.Net.IPAddress instance
if (System.Net.IPAddress.TryParse(strIP , out myAddress)) 
    // IP is valid
else
    // IP isn't valid

Ответ 5

Без использования класса IPAddress и проверки на байт, что намного лучше, чем подход Int <256.

    public Boolean CheckIPValid(String strIP)
    {
        //  Split string by ".", check that array length is 4
        string[] arrOctets = strIP.Split('.');
        if (arrOctets.Length != 4)
            return false;

        //Check each substring checking that parses to byte
        byte obyte = 0;
        foreach (string strOctet in arrOctets)
            if (!byte.TryParse(strOctet, out obyte)) 
                return false;

        return true;
    }

Ответ 6

Лучшее решение Regex:

^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

С#

Regex.IsMatch(value, "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")

Ответ 7

Удивленный никто не предлагал решение Regex. Все, что вам нужно, это включить System.Text.RegularExpressions. Для читаемости как в реальном коде, так и в этом примере, я ВСЕГДА разбиваю мой шаблон регулярного выражения на массив строк и затем присоединяюсь к нему.

        // Any IP Address
        var Value = "192.168.0.55"; 
        var Pattern = new string[]
        {
            "^",                                            // Start of string
            @"([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.",    // Between 000 and 255 and "."
            @"([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.",
            @"([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.",
            @"([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])",      // Same as before, no period
            "$",                                            // End of string
        };

        // Evaluates to true 
        var Match = Regex.IsMatch(Value, string.Join(string.Empty, Pattern));

Ответ 8

попробуйте с этим:

private bool IsValidIP(String ip)
    {
        try
        {
            if (ip == null || ip.Length == 0)
            {
                return false;
            }

            String[] parts = ip.Split(new[] { "." }, StringSplitOptions.None);
            if (parts.Length != 4)
            {
                return false;
            }

            foreach (String s in parts)
            {
                int i = Int32.Parse(s);
                if ((i < 0) || (i > 255))
                {
                    return false;
                }
            }
            if (ip.EndsWith("."))
            {
                return false;
            }

            return true;
        }
        catch (Exception e)
        {
            return false;
        }
    }

Ответ 9

Если вы хотите просто проверить, действует ли только действие:

bool isValid = IPAddress.TryParse(stringIP, out IPAddress _);

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

Ответ 10

Вы можете обрабатывать так, что это либо ipv4, либо ipv6:

    public static string CheckIPValid(string strIP)
    {
        //IPAddress result = null;
        //return !String.IsNullOrEmpty(strIP) && IPAddress.TryParse(strIP, out result);
        IPAddress address;
        if (IPAddress.TryParse(strIP, out address))
        {
            switch (address.AddressFamily)
            {
                case System.Net.Sockets.AddressFamily.InterNetwork:
                    // we have IPv4
                    return "ipv4";
                //break;
                case System.Net.Sockets.AddressFamily.InterNetworkV6:
                    // we have IPv6
                    return "ipv6";
                //break;
                default:
                    // umm... yeah... I'm going to need to take your red packet and...
                    return null;
                    //break;
            }
        }
        return null;
    }