Проверка 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
).
Любая помощь наиболее ценится.
Ответы
Ответ 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() или регулярные выражения.
Ответ 7
Да, это действительные адреса. Подробнее см. http://en.wikipedia.org/wiki/IPv4#Address_representations.
Ответ 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
}