2011-02-11 10 views
11

Estoy tratando de analizar una cadena que contiene una dirección IP y un puerto usando IPAddress.Parse. Esto funciona bien con direcciones IPv6 pero no con direcciones IPv4. ¿Puede alguien explicar por qué sucede esto?IPAddress.Parse() usando el puerto en IPv4

El código que estoy usando es:

IPAddress.Parse("[::1]:5"); //Valid 
IPAddress.Parse("127.0.0.1:5"); //null 
+0

Aquí no obtienen un valor nulo para el segundo ejemplo. Obtengo una excepción Una dirección IPv4 no incluye números de puerto. Tenga en cuenta que está tratando de analizar una cadena que contenga "una dirección IP * y * un puerto". Entonces la excepción tiene sentido. Por qué funciona la versión IPv6, no sé. –

+4

'IPAddress.Parse (" [:: 1]: 5 ");' es válido, * pero * el ': 5' se elimina silenciosamente! Si inspecciona el objeto resultante, puede ver que el resultado es simplemente ':: 1'. Esto podría ser un error en el método 'IPAddress.Parse' ... – hangy

+0

@Martinho Fernandes - no es un error en el analizador IP6, [:: 1]: 5 es una dirección IP6 válida porque el separador es ':' , no '::' (http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-4) - ** y ** la combinación de puertos está integrada en el IP6 especificación también, sin embargo, no se espera que la entidad IPAddress * contenga * el puerto. Es posible que [a, b, c, d]: port para ipv4 también esté permitido ya que la especificación IP6 parece sugerir que era parte de la especificación IP4 –

Respuesta

5

IPAddress.Parse está destinado a tener una cadena que contiene una dirección IP en notación decimal con puntos para IPv4 y en notación hexadecimal con dos puntos para IPv6. Así que su primer ejemplo funciona para IPv6 y su segundo ejemplo falla porque no admite un puerto para IPv4. Enlace http://msdn.microsoft.com/en-us/library/system.net.ipaddress.parse.aspx

9

Esto sucede porque el puerto no es parte de la dirección IP. Pertenece a TCP/UDP, y tendrá que quitarlo primero. La clase Uri podría ser útil para esto.

+0

+1, ya que responde a la pregunta '¿por qué?'. @Francisco Silva - Y luego puedes ver las respuestas @abatischev o @Tedds para saber cómo manejar –

6

IPAddress no es IP + puerto. Desea IPEndPoint.

Ejemplo de http://www.java2s.com/Code/CSharp/Network/ParseHostString.htm

public static void ParseHostString(string hostString, ref string hostName, ref int port) 
{ 
    hostName = hostString; 
    if (hostString.Contains(":")) 
    { 
     string[] hostParts = hostString.Split(':'); 

     if (hostParts.Length == 2) 
     { 
     hostName = hostParts[0]; 
     int.TryParse(hostParts[1], out port); 
     } 
    } 
}

Editar: Ok, voy a admitir que no era la solución más elegante. Prueba con esto que escribí (sólo para usted) en su lugar:

// You need to include some usings: 
using System.Text.RegularExpressions; 
using System.Net; 

// Then this code (static is not required): 
private static Regex hostPortMatch = new Regex(@"^(?<ip>(?:\[[\da-fA-F:]+\])|(?:\d{1,3}\.){3}\d{1,3})(?::(?<port>\d+))?$", System.Text.RegularExpressions.RegexOptions.Compiled); 
public static IPEndPoint ParseHostPort(string hostPort) 
{ 
    Match match = hostPortMatch.Match(hostPort); 
    if (!match.Success) 
     return null; 

    return new IPEndPoint(IPAddress.Parse(match.Groups["ip"].Value), int.Parse(match.Groups["port"].Value)); 
}

Tenga en cuenta que éste acepta sólo la dirección IP, nombre de host no. Si desea dar soporte al nombre de host, tendrá que resolverlo en IP o no usar IPAddress/IPEndPoint.

+0

Gracias por tu esfuerzo, pero ya había encontrado una solución para mi problema al usar la clase Uri. Estaba intrigado sobre por qué el comportamiento de IPAddress.Parse en estas dos situaciones. –

+0

El segundo RegEx de su ejemplo de código ni siquiera coincide con el más básico de los puntos finales, '127.0.0.1: 80'. – Kehlan

19
Uri url; 
IPAddress ip; 
if (Uri.TryCreate(String.Format("http://{0}", "127.0.0.1:5"), UriKind.Absolute, out url) && 
    IPAddress.TryParse(url.Host, out ip)) 
{ 
    IPEndPoint endPoint = new IPEndPoint(ip, url.Port); 
} 
+1

Tenga en cuenta que esto no funciona con IPv6 sin [] como ':: 1: 1024' – NiKiZe

Cuestiones relacionadas