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,000 毫秒。

经过数小时在客户端和服务器上的计时调试后,我发现它的速度很慢。
解决方法是从此更改代码:

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

对此:

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

这让一切变得不同。现在一次通过大约需要 10 毫秒,而 10 次通过则不到 100 毫秒。

为什么???

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

如果您没有启用日志记录,上面的代码几乎是无操作的

第二个 ctor(string hostname, int port) 当然可以完成所有这些以及更多,但是“更多”的一部分是对您在第二个示例中使用的相同 TcpClient.Connect() 方法的调用。即,在这两种情况下,执行的代码几乎完全相同。我挖了进去,因为我想知道 MS 代码怎么会有这么奇怪的问题——我可以通过查看拆解来判断,他们没有奇怪的问题。我想我可能会看到一些奇怪的 DNS 查找问题,或者类似但没有骰子。

几乎可以保证连接套接字会很慢,但我预计这最多需要 100 或 200 毫秒,除非您的 Internet 连接、DNS 服务器或代理服务器非常糟糕。但是我看不到在您的 2 个案例中会导致明显不同的行为,但有 1 个例外。您的示例在显示您的 using 子句可能有何不同方面并不完整。如果套接字上有触发缓慢行为的清理代码,则您的两个示例可能会有所不同。

于 2013-08-22T22:25:00.510 回答