5

かなりシンプルなクライアントサーバーネットワークアプリを書きたいと思います。私は純粋なIPv4ネットワークのみを使用していますが、コードを将来にわたって利用できるようにすると便利です。WCFの予備調査により、セットアップが非常に複雑で、理解しにくいことがわかったため、おそらくTcpListener/TcpClientを使用します。

クライアント側の場合、.NETは、IPv4またはIPv6アドレス(IPv4アドレスにポート番号が含まれる)を含む文字列を自動的にデコードする機能を提供しますか?ドメイン名を解決できる場合はボーナスポイント。

サーバー側では、IPv6はポート番号を使用しないと聞きましたが、リッスンするポートに相当するものは何ですか?IPv4ポート番号の文字列をIPv6に相当するものと区別する標準的な方法はありますか?気にしないでください。IPv6サービスには、IPv4サービスと同じように16ビットのポート番号があります。

4

4 に答える 4

6

はいSystem.Net.IPAddress

IPAddress.Parse( "fe80::21c:42ff:fe00:8%vnic0" );
IPAddress.Parse( "127.0.0.1" );

そして、IPv4 または v6 をテストするには

if( IPAddress.Parse(...).AddressFamily == AddressFamily.InterNetwork )
  // IPv4 address
于 2011-03-11T18:53:58.403 に答える
2

@Qwertie は次のように述べています。

IPv6 アドレスにもコロンが含まれているため、ポート番号を含む IPv6 アドレスまたは IPv4 アドレスをデコードする適切な方法は何だろうか。

他の人が指摘したように、ポート番号は IP アドレス (IPv4 または IPv6) の一部ではありません。IP アドレスはアトミックな符号なし整数です (IPv4 は 32 ビット、IPv6 は 128 ビット)。文字形式 (URI など) で表される場合、ポート番号 (およびその他の情報) と組み合わせることができます。URI 内では、ホストとポートは URI の権限部分の一部です。

を使用して、URI を構成部分に解析できますSystem.Uri。URIのAuthority部分は、次のプロパティで構成されます: Host, Port(および、オプションで非推奨の、ユーザー名とパスワードで構成される UserInfo サブコンポーネント)。プロパティHostNameTypeは、取得したホスト名の種類、列挙型の値を示しますUriHostNameType: Dns、Ipv4、Ipv6、またはその他。

RFC 3986の付録 B で定義されている正規表現を使用して、URI をその構成要素に解析することもできます。

付録 B. 正規表現による URI 参照の解析
「first-match-wins」アルゴリズムは「greedy」アルゴリズムと同じです。 POSIX 正規表現で使用される曖昧さ回避方法です。 を解析するために正規表現を使用するのは自然でありふれたことです。 URI 参照の潜在的な 5 つのコンポーネント。
次の行は、a を分解するための正規表現です。 そのコンポーネントへの整形式の URI 参照。
^(([^:/?#]+):)?(//([^/?#] ))?([^?#] )(\?([^#] ))?(#(. )))? 12 3 4 5 6 7 8 9
上記の 2 行目の数字は、読みやすくするためだけのものです。 これらは、各部分式の基準点を示します (つまり、それぞれ ペア括弧)。部分式に一致した値を参照します <n> として $<n>。たとえば、上記の式を
http://www.ics.uci.edu/pub/ietf/uri/#Related
と照合する と、次の部分式が一致します。
$1 = http: $2 = http $3 = //www.ics.uci.edu $4 = www.ics.uci.edu $5 = /pub/ietf/uri/ $6 = $7 = $8 = #関連 $9 = 関連
<undefined> は、コンポーネントが存在しないことを示します。 上記の例のクエリ コンポーネントの場合です。したがって、私たちは 5 つのコンポーネントの値を次のように決定できます。
スキーム = $2 権限 = $4 パス = $5 クエリ = $7 フラグメント = $9
反対方向に進むと、URI 参照を次から再作成できます。 セクション5.3のアルゴリズムを使用してそのコンポーネント。

ただし、この正規表現は少し間違っているようです。RFC 3986 とその前身である RFC 2396の正誤表によると:

正誤表 ID: 1933
ステータス: 検証済み タイプ: テクニカル 報告者: スキップ・ジール 報告日: 2009-10-25 検証者名: Peter Saint-Andre 検証日: 2010-11-11
セクション付録 B の記述:
^(([^:/?#]+):)?(//([^/?#] ))?([^?#] )(\ ?([^#] ))?(#(. ))? /^(([^:\/?#]+):)?(\/\/([^\/?#]
) )?([^?#] )(\?([^ #] ))?(#(. ))?/ 注:


正規表現はスラッシュ ("/") で区切られます。その中にスラッシュ バックスラッシュ ("\") を前に付ける必要があります。
Peter: これは RFC 3986 にも当てはまります。

于 2011-03-11T20:16:19.760 に答える
2

System.Net.IPAddress を使用して、有効な IPv4 および IPv6 アドレスを表す文字列を解析できます。System.Net.Dns を使用して、ネットワーク上のホスト名とアドレスを解決できます。

両方のための、

using System.Net;
于 2011-03-11T18:55:24.977 に答える
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);
}

パラメータは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);
}

アドレスに接続せずにアドレスをデコードするには (たとえば、アドレスが有効であることを確認するため、または 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;
}

興味深いことに、Dns.GetHostAddresses複数のアドレスを返すことができます。と聞いてみたところ、最初の住所だけでいいらしい。

FormatException構文エラーまたはドメイン名 (または)の解決に問題がある場合、例外が発生しますSocketException。ユーザーがドメイン名を指定した場合resolveDns==false、このメソッドは を返しますnull

于 2011-03-11T22:14:33.357 に答える