Je refacture mon code et je voulais utiliser la méthode IPAddress.TryParse
pour valider si une chaîne est une adresse IPv4 valide au lieu d'utiliser des expressions régulières:
public static bool IsIPv4(string value)
{
IPAddress address;
if (IPAddress.TryParse(value, out address))
{
if (address.AddressFamily == AddressFamily.InterNetwork)
{
return true;
}
}
return false;
}
Mon test d'unité échoue maintenant car ces valeurs d'entrée renvoient true
et sont analysées avec les objets IPAddress
suivants:
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}
Est-ce que ça a du sens? Je peux voir que 0.0.0.0
est techniquement une adresse IPv4 valide, même si cela n’a aucun sens pour l’utilisateur de le saisir. Qu'en est-il des deux autres? Pourquoi sont-ils convertis tels quels et devrais-je les traiter comme valables même si cela peut ne pas être transparent pour l'utilisateur, qui a peut-être simplement oublié d'entrer les points (65536
au lieu de 6.5.5.36
).
Toute aide est très appréciée.
Il semble que la documentation de IPAddress.Parse
rationalise ce comportement en indiquant que la saisie de moins de parties est pratique pour la saisie d’adresses de classes A et B. Si vous voulez forcer une adresse en quatre parties, vous voudrez peut-être simplement vérifier qu'il y a trois points dans l'adresse avant de l'envoyer à IPAddress.TryParse
, je suppose.
Un code pour votre référence:
// 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
Le travail de IPAddress.TryParse () ne consiste pas à vérifier si la chaîne est une adresse IP valide, mais si le contenu de la chaîne peut être analysé (c'est-à-dire converti) en une adresse IP valide. adresse.
Toutes les options de vos cas de test peuvent en fait être analysées pour représenter et IP. En résumé, vos scénarios de test sont valides. Le problème est que les données de vos scénarios de test ne sont pas valides ou que vous n'utilisez pas les bons outils dans votre scénario de test pour obtenir le résultat attendu.
Si vous testez spécifiquement un IPv4 valide, avec exactement 4 quads (chacun étant un entier compris entre 0 et 255), et que vous souhaitez éviter les expressions rationnelles, vous pouvez au lieu de cela diviser puis analyser et valider.
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;
}
Si vous voulez être très strict sur votre entrée, vous pouvez alors comparer la version ToString()
de la IPAddress
analysée et rejeter l'entrée si elles sont différentes.
L'adresse du zéro absolu, entre autres, devrait être traitée comme un cas spécial.
Je suggère:
public bool IsValidIp(string addr)
{
IPAddress ip;
bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
return valid;
}
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;
}
D'autres réponses autorisent IPv6 ou permettent une entrée telle que "1.-0.1.1".
Le nombre de parties (chaque partie est séparée par un point) dans ipString détermine la manière dont l'adresse IP est construite. Une adresse en une partie est stockée directement dans l'adresse du réseau. Une adresse en deux parties, pratique pour spécifier une adresse de classe A, place la partie principale dans le premier octet et la partie suivante dans les trois octets les plus à droite de l'adresse réseau. Une adresse en trois parties, pratique pour spécifier une adresse de classe B, place la première partie dans le premier octet, la seconde partie dans le deuxième octet et la dernière dans les deux octets les plus à droite de l'adresse réseau. Par exemple:
Nombre de pièces et exemple ipString Adresse IPv4 pour IPAddress
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
Vous souhaiterez peut-être consulter la documentation MSDN http://msdn.Microsoft.com/en-us/library/system.net.ipaddress.parse.aspx
Votre meilleur pari sera IPAddress.ToString () ou des expressions régulières.
Bien que cette question ait reçu une réponse il y a deux ans environ, je pense qu'il est pertinent de revenir sur ce que j'ai découvert lorsque je cherchais la même chose aujourd'hui, et après avoir trouvé cette page, j'ai décidé que j'étais trop paresseux pour effectuer toutes les validations par étapes. .
Si les informations sont acceptées via Form
et TextBox
, il serait dans votre intérêt d’utiliser plutôt un MaskedTextBox
. Vous pouvez forcer l'utilisateur à entrer des informations au format d'adresse IP au lieu de devoir vous-même tenter de deviner.
Le masque à utiliser pour cette validation est 990.990.990.990
, qui indique OptionalNumber, OptionalNumber, MandatoryNumber
car 1.1.1.1
, 10.10.10.10
et 123.123.123.123
sont tous des formats d'adresse IP valides. Les masques sont au même format que Microsoft utilise dans Access.
Oui, ce sont des adresses valides. Voir http://en.wikipedia.org/wiki/IPv4#Address_representations pour plus d'informations.
Cela a du sens, car 65536 est égal à 0x00010000, ou 0.1.0.0. J'imagine que TryParse acceptera également les nombres hexadécimaux. Dans tous les cas, je ne pense pas que vous souhaitiez accepter une telle valeur d'un utilisateur normal, mais je suppose que cela dépend de l'utilisateur final.
Le code ci-dessous utilise regex, suggéré par 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
}