2010-04-28 19 views
32

Desde IPEndpoint contiene un método que da salida a ToString():mejor manera de crear IPEndPoint de cadena

10.10.10.10:1010

También debe haber Parse() y/o método de TryParse() pero hay ISN' t.

Puedo dividir la cadena en el : y analizar una dirección IP y un puerto.

¿Pero hay una manera más elegante?

Respuesta

1

Cree un método de extensión Parse and TryParse. Supongo que es más elegante.

+6

¿En el hilo? No estoy seguro si me gusta eso ... – sbhl

26

Esta es una solución ...

public static IPEndPoint CreateIPEndPoint(string endPoint) 
{ 
    string[] ep = endPoint.Split(':'); 
    if(ep.Length != 2) throw new FormatException("Invalid endpoint format"); 
    IPAddress ip; 
    if(!IPAddress.TryParse(ep[0], out ip)) 
    { 
     throw new FormatException("Invalid ip-adress"); 
    } 
    int port; 
    if(!int.TryParse(ep[1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port)) 
    { 
     throw new FormatException("Invalid port"); 
    } 
    return new IPEndPoint(ip, port); 
} 

Editar: Se ha añadido una versión que se encargará de IPv4 e IPv6 al anterior sólo se ocupa de IPv4.

// Handles IPv4 and IPv6 notation. 
public static IPEndPoint CreateIPEndPoint(string endPoint) 
{ 
    string[] ep = endPoint.Split(':'); 
    if (ep.Length < 2) throw new FormatException("Invalid endpoint format"); 
    IPAddress ip; 
    if (ep.Length > 2) 
    { 
     if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip)) 
     { 
      throw new FormatException("Invalid ip-adress"); 
     } 
    } 
    else 
    { 
     if (!IPAddress.TryParse(ep[0], out ip)) 
     { 
      throw new FormatException("Invalid ip-adress"); 
     } 
    } 
    int port; 
    if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port)) 
    { 
     throw new FormatException("Invalid port"); 
    } 
    return new IPEndPoint(ip, port); 
} 
+1

¿Esta es más o menos la solución que insinué en la pregunta? Pero muy bien hecho. – sbhl

+0

@S_Hultqvist, lo sé, me perdí esa parte la primera vez que leí tu pregunta. No me di cuenta hasta después de haber publicado mi respuesta. –

+1

No es bueno: CreateIPEndPoint (nuevo IPEndPoint (IPAddress.Parse ("2001: 740: 8deb: 0 :: 1"), 5222) .ToString()) –

1

El código de análisis es sencillo para un punto final IPv4, pero IPEndPoint.ToString() en una dirección IPv6 también utiliza la misma notación de colon, pero los conflictos con la notación de colon de la dirección IPv6. Esperaba que Microsoft gastara el esfuerzo escribiendo este feo código de análisis en su lugar, pero creo que tendré que ...

2

Esto hará IPv4 e IPv6. Un método de extensión para esta funcionalidad sería en System.string. No estoy seguro de querer esta opción para cada cadena que tengo en el proyecto.

private static IPEndPoint IPEndPointParse(string endpointstring) 
{ 
    string[] values = endpointstring.Split(new char[] {':'}); 

    if (2 > values.Length) 
    { 
     throw new FormatException("Invalid endpoint format"); 
    } 

    IPAddress ipaddress; 
    string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray()); 
    if (!IPAddress.TryParse(ipaddressstring, out ipaddress)) 
    { 
     throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", ipaddressstring)); 
    } 

    int port; 
    if (!int.TryParse(values[values.Length - 1], out port) 
    || port < IPEndPoint.MinPort 
    || port > IPEndPoint.MaxPort) 
    { 
     throw new FormatException(string.Format("Invalid end point port '{0}'", values[values.Length - 1])); 
    } 

    return new IPEndPoint(ipaddress, port); 
} 
+0

Probablemente has querido decir 'if (2 drdaeman

+1

@drdaeman no, no lo hizo. (Piensa en compatibilidad con IPv6). –

+0

Gracias Nick. Usted es exactamente correcto. –

23

que tenían el requisito de analizar un IPEndPoint con IPv6, V4 y nombres de host. La solución escribí aparece a continuación:

public static IPEndPoint Parse(string endpointstring) 
    { 
     return Parse(endpointstring, -1); 
    } 

    public static IPEndPoint Parse(string endpointstring, int defaultport) 
    { 
     if (string.IsNullOrEmpty(endpointstring) 
      || endpointstring.Trim().Length == 0) 
     { 
      throw new ArgumentException("Endpoint descriptor may not be empty."); 
     } 

     if (defaultport != -1 && 
      (defaultport < IPEndPoint.MinPort 
      || defaultport > IPEndPoint.MaxPort)) 
     { 
      throw new ArgumentException(string.Format("Invalid default port '{0}'", defaultport)); 
     } 

     string[] values = endpointstring.Split(new char[] { ':' }); 
     IPAddress ipaddy; 
     int port = -1; 

     //check if we have an IPv6 or ports 
     if (values.Length <= 2) // ipv4 or hostname 
     { 
      if (values.Length == 1) 
       //no port is specified, default 
       port = defaultport; 
      else 
       port = getPort(values[1]); 

      //try to use the address as IPv4, otherwise get hostname 
      if (!IPAddress.TryParse(values[0], out ipaddy)) 
       ipaddy = getIPfromHost(values[0]); 
     } 
     else if (values.Length > 2) //ipv6 
     { 
      //could [a:b:c]:d 
      if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]")) 
      { 
       string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray()); 
       ipaddy = IPAddress.Parse(ipaddressstring); 
       port = getPort(values[values.Length - 1]); 
      } 
      else //[a:b:c] or a:b:c 
      { 
       ipaddy = IPAddress.Parse(endpointstring); 
       port = defaultport; 
      } 
     } 
     else 
     { 
      throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring)); 
     } 

     if (port == -1) 
      throw new ArgumentException(string.Format("No port specified: '{0}'", endpointstring)); 

     return new IPEndPoint(ipaddy, port); 
    } 

    private static int getPort(string p) 
    { 
     int port; 

     if (!int.TryParse(p, out port) 
     || port < IPEndPoint.MinPort 
     || port > IPEndPoint.MaxPort) 
     { 
      throw new FormatException(string.Format("Invalid end point port '{0}'", p)); 
     } 

     return port; 
    } 

    private static IPAddress getIPfromHost(string p) 
    { 
     var hosts = Dns.GetHostAddresses(p); 

     if (hosts == null || hosts.Length == 0) 
      throw new ArgumentException(string.Format("Host not found: {0}", p)); 

     return hosts[0]; 
    } 

Esto ha sido probado para trabajar con los siguientes ejemplos:

  • 0.0.0.0:100
  • 0.0.0.0
  • [:: 1 ]: 100
  • [:: 1]
  • :: 1
  • [a: b: c: d]
  • [a: b: c: d]: 100
  • example.org
  • example.org:100
1

Esta es mi opinión sobre el análisis sintáctico de un IPEndPoint. El uso de la clase Uri evita tener que manejar los detalles de IPv4/6 y la presencia o no del puerto. Podría modificar el puerto predeterminado para su aplicación.

public static bool TryParseEndPoint(string ipPort, out System.Net.IPEndPoint result) 
    { 
     result = null; 

     string scheme = "iiiiiiiiiaigaig"; 
     GenericUriParserOptions options = 
      GenericUriParserOptions.AllowEmptyAuthority | 
      GenericUriParserOptions.NoQuery | 
      GenericUriParserOptions.NoUserInfo | 
      GenericUriParserOptions.NoFragment | 
      GenericUriParserOptions.DontCompressPath | 
      GenericUriParserOptions.DontConvertPathBackslashes | 
      GenericUriParserOptions.DontUnescapePathDotsAndSlashes; 
     UriParser.Register(new GenericUriParser(options), scheme, 1337); 

     Uri parsedUri; 
     if (!Uri.TryCreate(scheme + "://" + ipPort, UriKind.Absolute, out parsedUri)) 
      return false; 
     System.Net.IPAddress parsedIP; 
     if (!System.Net.IPAddress.TryParse(parsedUri.Host, out parsedIP)) 
      return false; 

     result = new System.Net.IPEndPoint(parsedIP, parsedUri.Port); 
     return true; 
    } 
2

aquí está mi versión de análisis de texto para IPEndPoint:

private static IPEndPoint ParseIPEndPoint(string text) 
{ 
    Uri uri; 
    if (Uri.TryCreate(text, UriKind.Absolute, out uri)) 
     return new IPEndPoint(IPAddress.Parse(uri.Host), uri.Port < 0 ? 0 : uri.Port); 
    if (Uri.TryCreate(String.Concat("tcp://", text), UriKind.Absolute, out uri)) 
     return new IPEndPoint(IPAddress.Parse(uri.Host), uri.Port < 0 ? 0 : uri.Port); 
    if (Uri.TryCreate(String.Concat("tcp://", String.Concat("[", text, "]")), UriKind.Absolute, out uri)) 
     return new IPEndPoint(IPAddress.Parse(uri.Host), uri.Port < 0 ? 0 : uri.Port); 
    throw new FormatException("Failed to parse text to IPEndPoint"); 

}

probado ingenio h:

1

Si el número de puerto se proporciona siempre después de un ':', el siguiente método puede ser una opción más elegante (en longitud de código en lugar de eficiencia).

public static IPEndpoint ParseIPEndpoint(string ipEndPoint) { 
    int ipAddressLength = ipEndPoint.LastIndexOf(':'); 
    return new IPEndPoint(
     IPAddress.Parse(ipEndPoint.Substring(0, ipAddressLength)), 
     Convert.ToInt32(ipEndPoint.Substring(ipAddressLength + 1))); 
} 

Funciona bien para mi aplicación simple sin tener en cuenta el formato de dirección IP compleja.

Cuestiones relacionadas