2010-04-28 6 views
32

Od IPEndpoint zawiera ToString() metodę wyjścia:Najlepszy sposób, aby utworzyć IPEndpoint z ciągiem

10.10.10.10:1010

Nie powinno być również Parse() i/lub TryParse() metoda ale nieprawdaż” t.

Mogę podzielić ciąg na : i przeanalizować adres IP i port.

Ale czy istnieje bardziej elegancki sposób?

Odpowiedz

1

Utwórz metodę rozszerzenia Parse i TryParse. Sądzę, że to jest bardziej eleganckie.

+6

Na sznurku? Nie jestem pewien, czy to lubię ... – sbhl

26

Jest jedno rozwiązanie ...

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); 
} 

Edycja: Dodano wersję, która będzie obsługiwać IPv4 i IPv6 poprzedni obsługuje tylko protokół 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

To jest mniej więcej rozwiązanie, które zasugerowałem w pytaniu? Ale ładnie wykonane. – sbhl

+0

@S_Hultqvist, wiem, tęskniłem za tą częścią za pierwszym razem, kiedy przeczytałem twoje pytanie. Nie zauważyłem tego, dopóki nie napisałem swojej odpowiedzi. –

+1

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

1

Kod parsowania jest prosta do punktu końcowego IPv4, ale IPEndPoint.ToString() na adres IPv6 wykorzystuje również ten sam zapis jelita grubego, ale konflikty z notacją okrężnicy adres w IPv6. Miałem nadzieję, że Microsoft wyda wysiłek, pisząc ten brzydki kod parsujący, ale myślę, że będę musiał ...

2

To zrobi IPv4 i IPv6. Metoda rozszerzenia dla tej funkcji będzie dostępna w System.string. Nie jestem pewien, czy chcę tej opcji dla każdego łańcucha, który mam w projekcie.

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

Prawdopodobnie miałeś na myśli 'if (2 drdaeman

+1

@drdaeman nie, on nie. (Pomyśl o obsłudze protokołu IPv6). –

+0

Dzięki Nick. Jesteś dokładnie poprawny. –

23

Miałem wymagania parsowania IPEndpoint z IPv6, v4 i hostname. Roztwór pisze się, że wymienione poniżej:

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]; 
    } 

ten został przetestowany w następujących przykładach:

  • 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

to my odbioru na przetwarzaniu w IPEndPoint. Korzystanie z klasy Uri pozwala uniknąć konieczności radzenia sobie ze specyfikacją IPv4/6 oraz obecności lub braku portu. Możesz zmodyfikować domyślny port dla swojej aplikacji.

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

Oto moja wersja analizowania tekstu do 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"); 

}

Sprawdzony dowcip H:

1

Jeśli numer portu jest zawsze dostarczane po ':', następująca metoda może być bardziej eleganckim rozwiązaniem (długość kodu zamiast wydajność).

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))); 
} 

To działa dobrze dla mojej prostej aplikacji, nie biorąc pod uwagę złożonego formatu adresu IP.