Best way to create IPEndpoint from string

后端 未结 13 1908
失恋的感觉
失恋的感觉 2020-12-03 06:33

Since IPEndpoint contains a ToString() method that outputs:

10.10.10.10:1010

There should also be

相关标签:
13条回答
  • 2020-12-03 07:10

    This will do IPv4 and IPv6. An extension method for this functionality would be on System.string. Not sure I want this option for every string I have in the project.

    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 讨论(0)
  • 2020-12-03 07:13

    Apparently, IPEndPoint.Parse and IPEndPoint.TryParse were added in .NET Core 3.0.

    In case you're targeting it, give those methods a try! The implementation is seen in the link above.

    0 讨论(0)
  • 2020-12-03 07:15

    I had the requirement of parsing an IPEndpoint with IPv6, v4 and hostnames. The solution I wrote is listed below:

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

    This has been tested to work with the following examples:

    • 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
    0 讨论(0)
  • 2020-12-03 07:15

    Here is my version of parsing text to 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");
    }
    

    Tested with:

    • 0.0.0.0
    • 0.0.0.0:100
    • [::1]:100
    • [::1]:0
    • ::1
    • [2001:db8:85a3:8d3:1319:8a2e:370:7348]
    • [2001:db8:85a3:8d3:1319:8a2e:370:7348]:100
    • http://0.0.0.0
    • http://0.0.0.0:100
    • http://[::1]
    • http://[::1]:100
    • https://0.0.0.0
    • https://[::1]
    0 讨论(0)
  • 2020-12-03 07:15

    If the port number is always provided after a ':', the following method may be a more elegant option (in code length instead of efficiency).

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

    It works fine for my simple application without considering complex IP address format.

    0 讨论(0)
  • 2020-12-03 07:16

    The parsing code is simple for an IPv4 endpoint, but IPEndPoint.ToString() on an IPv6 address also uses the same colon notation, but conflicts with the IPv6 address's colon notation. I was hoping Microsoft would spend the effort writing this ugly parsing code instead, but I guess I'll have to...

    0 讨论(0)
提交回复
热议问题