是否有针对ipv4和ipv6地址的标准.NET解码器?

Qwe*_*tie 5 .net ipv4 ipv6

我想写一个相当简单的客户端 - 服务器网络应用程序.我只使用纯粹的IPv4网络,但是对于面向未来的代码我会很高兴.我可能会使用TcpListener/TcpClient,因为对WCF的初步调查显示它设置过于复杂并且难以理解.

对于客户端,.NET是否提供了一种工具来自动解码包含IPv4或IPv6地址的字符串(其中IPv4地址包含端口号)?奖励积分,如果它可以解析域名.

对于服务器端,我听说IPv6不使用端口号,那么什么相当于要监听的端口,是否有一种标准方法可以区分IPv4端口号字符串和IPv6等价物?没关系,IPv6服务有16位端口号,就像IPv4服务器一样.

Pau*_*der 6

是的System.Net.IPAddress

IPAddress.Parse( "fe80::21c:42ff:fe00:8%vnic0" );
IPAddress.Parse( "127.0.0.1" );
Run Code Online (Sandbox Code Playgroud)

并测试IPv4或v6

if( IPAddress.Parse(...).AddressFamily == AddressFamily.InterNetwork )
  // IPv4 address
Run Code Online (Sandbox Code Playgroud)

  • 这不是有效的IP地址.端口号不是TCP/IP堆栈的IP部分的一部分.IP地址没有端口.你正在使用的是更接近_URI_,它也可以与Uri类解析. (3认同)
  • IP地址_don't_包含端口号 - 在v4或v6中.您正在尝试解析使用IP地址作为主机名的_URI_.只需使用Uri就可以了. (3认同)

Qwe*_*tie 0

正如 Paul 提到的,没有端口号的纯 IP 地址可以通过IPAddress.Parse(). 但是,如果存在端口号和/或主机名(12.34.56.78:90 或 www.example.com:5555),则需要采用不同的方法。如果你想使用 TcpClient 进行连接,这个函数将这样做:

public static TcpClient Connect(string ipAndPort, int defaultPort)
{
    if (ipAndPort.Contains("/"))
        throw new FormatException("Input should only be an IP address and port");

    // Uri requires a prefix such as "http://", "ftp://" or even "foo://".
    // Oddly, Uri accepts the prefix "//" UNLESS there is a port number.
    Uri uri = new Uri("tcp://" + ipAndPort);

    string ipOrDomain = uri.Host;
    int port = uri.Port != -1 ? uri.Port : defaultPort;
    return new TcpClient(ipOrDomain, port);
}
Run Code Online (Sandbox Code Playgroud)

defaultPort参数指定在输入字符串没有端口时要使用的端口。例如:

using (NetworkStream s = Connect("google.com", 80).GetStream())
{
    byte[] line = Encoding.UTF8.GetBytes("GET / HTTP/1.0\r\n\r\n");
    s.Write(line, 0, line.Length);

    int b;
    while ((b = s.ReadByte()) != -1)
        Console.Write((char)b);
}
Run Code Online (Sandbox Code Playgroud)

要在不连接的情况下解码地址(例如,验证它是否有效,或者因为您通过需要 IP 地址的 API 进行连接),此方法将执行此操作(并可选择执行 DNS 查找):

public static IPAddress Resolve(string ipAndPort, ref int port, bool resolveDns)
{
    if (ipAndPort.Contains("/"))
        throw new FormatException("Input address should only contain an IP address and port");

    Uri uri = new Uri("tcp://" + ipAndPort);

    if (uri.Port != -1)
        port = uri.Port;
    if (uri.HostNameType == UriHostNameType.IPv4 || uri.HostNameType == UriHostNameType.IPv6)
        return IPAddress.Parse(uri.Host);
    else if (resolveDns)
        return Dns.GetHostAddresses(uri.Host)[0];
    else
        return null;
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,Dns.GetHostAddresses可以返回多个地址。我问了一下,显然直接取第一个地址就可以了。

如果存在语法错误或解析域名(FormatExceptionSocketException)时出现问题,则会引发异常。但如果用户指定了域名resolveDns==false,则此方法返回null