5

に問題がありSystem.Net.Sockets.TcpClientます。

簡単なテスト アプリは、接続を開いてデータを送信し、閉じるだけです。反対側には単純なサーバーがあり、そのパフォーマンスは問題ありません。

コードは次のようになります。

var client = new TcpClient("localhost", 1234);
using (var stream = client.GetStream())
using (var writer = new StreamWriter(stream))
{
    writer.Write("foo");
    writer.flush();
}
client.Close();

問題なく動作しますが、単体テストの実行に 1000 ミリ秒以上かかっていることに気付きました。10回というループに入れたところ、10,000ms以上でした。

クライアントとサーバーの両方でタイミングを合わせて何時間もデバッグした後、遅い場所を見つけました。
修正は、次のコードを変更することでした。

var client = new TcpClient("localhost", 1234);

これに:

var client = new TcpClient();
client.Connect("localhost", 1234);

それがすべての違いを生んだ。現在、1 回のパスには約 10ms かかり、10 回のパスは 100ms 弱です。

どうして???

4

2 に答える 2

5

http://msdn.microsoft.com/en-us/library/115ytk56(v=vs.110).aspxから:

「IPv6 が有効になっていて、TcpClient(String, Int32) メソッドが呼び出されて、IPv6 アドレスと IPv4 アドレスの両方に解決されるホストに接続する場合、IPv6 アドレスへの接続が最初に試行されてから、IPv4 アドレスが試行されます。これは影響を与える可能性があります。ホストが IPv6 アドレスをリッスンしていない場合に、接続を確立する時間を遅らせることです。」

デフォルトのコンストラクターもこれを行わない理由はわかりません (接続する前に AddressFamily を受け取り、IPv4 を指定するコンストラクターを使用する必要があると予想していました) が、明らかにそうではありません。

于 2014-12-18T19:16:26.037 に答える
-1

あなたはこの答えを気に入るはずです。私には意味がないのでわかりません。

Reflector を使用すると、v.2 アセンブリのデフォルトの ctor は

public TcpClient() : this(AddressFamily.InterNetwork)
{
    if (Logging.On)
    {
        Logging.Enter(Logging.Sockets, this, "TcpClient", (string) null);
    }
    if (Logging.On)
    {
        Logging.Exit(Logging.Sockets, this, "TcpClient", (string) null);
    }
}

ロギングを有効にしていない場合、上記のコードはほぼノーオペレーションです。

2 番目の ctor(string hostname, int port) はもちろんこれ以上のことをすべて行いますが、その「その他」の一部は、2 番目の例で使用するのと同じ TcpClient.Connect() メソッドの呼び出しです。つまり、実行されたコードはどちらの場合もほとんど同じです。私は、MS コードがなぜこのような奇妙な問題を抱えているのか疑問に思ったので、掘り下げました。DNS ルックアップに奇妙な問題が発生する可能性があると思いましたが、サイコロはありませんでした。

ソケットの接続はほぼ確実に遅い部分ですが、インターネット接続、DNS サーバー、またはプロキシ サーバーが非常に悪い場合を除き、これには最大で約 100 ミリ秒または 200 ミリ秒かかると予想されます。しかし、1 つの例外を除いて、2 つのケースで大幅に異なる動作を引き起こすものは何もありません。あなたの例は、using 節がどのように異なるかを示す点で完全ではありません。遅い動作をトリガーしているソケットにクリーンアップ コードがある場合、2 つの例に違いがある可能性があります。

于 2013-08-22T22:25:00.510 に答える