【问题标题】:Why is the TcpClient slower to connect with parameters in the constructor?为什么 TcpClient 与构造函数中的参数连接较慢?
【发布时间】:2014-12-19 03:16:26
【问题描述】:

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

这一切都不同了。现在一个 pass 大约需要 10ms,而 10 个 pass 则略小于 100ms。

为什么???

【问题讨论】:

  • 这篇文章的最后一句话是我对大多数.NET的感受
  • 我测试了它,没有发现任何区别。你能发布一个简单的、独立的代码(客户端+服务器)来显示问题吗?

标签: c# .net sockets tcpclient


【解决方案1】:

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

"如果启用了 IPv6 并且调用了 TcpClient(String, Int32) 方法以连接到同时解析为 IPv6 和 IPv4 地址的主机,则将首先尝试连接到 IPv6 地址,然后再尝试 IPv4 地址。这可能如果主机没有监听 IPv6 地址,则会延迟建立连接的时间。"

我不确定为什么默认构造函数也不这样做(我原以为您必须使用接受 AddressFamily 的构造函数并在连接之前指定 IPv4)但显然它没有。

【讨论】:

    【解决方案2】:

    你会喜欢这个答案的。我不知道,因为对我来说没有意义。

    使用 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 子句可能有何不同方面并不完整。如果在触发缓慢行为的套接字上有清理代码,那么您的 2 个示例可能会有所不同。

    【讨论】:

    • 不同之处在于添加了更多您通常用于调试问题的技术细节,您也分享了没有任何区别的内容。
    • 不是答案,只是很长的评论
    • 是的,这只是一个长评论,但你不能在 SO 上制作长 cmets -- 你有更好的方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 2014-08-10
    • 2021-07-02
    相关资源
    最近更新 更多