4

我尝试使用 TcpClient 发送/接收数据。我做了两个实验,发现了一些有趣的东西。

我在日本的服务器和英国的 TcpClient 中设置了 TcpListener。我一直向 TcpListener 发送 500 个字节,当 TcpListener 将 10KB 发送回 TcpClient 时。我在每个实验中保持这个发送/接收循环 500 次。

实验一:

在每个发送/接收循环中,我创建一个全新的 TcpClient(从创建之前开始计时)并发送/接收

实验二:

对于所有循环,我只有一个 TcpClient,它保持与 TcpListener 的连接并进行 500 次发送/接收。

结果:

一个循环的时间成本的平均值:

E1:1.8 秒,E2:0.49 秒。

我对这个结果感到非常惊讶。所以保持连接以持续发送/接收可以节省很多时间???将近 2/3 的时间。

这是真的???

谢谢

====新====

@Jon Skeet,@dbemerlin,感谢您的回复。我猜想 Tcp 握手需要一些时间工具。

所以我做了实验3。

我将 HttpListener 设置为服务器并使用 WebClient 发送/接收,数据大小完全相同。每次我使用新的 WebClient 在英国和日本之间发送/接收时。

结果为 0.86(500 次循环的平均值,即发送/接收)。

我假设 WebClient / HttpLisener 本身就是 Tcp,对吧?在我的实验中,它们如何比原始 TcpClient/TcpListener 更快?

再次感谢

4

2 回答 2

6

这并不特别令人惊讶,但这不是创建对象的成本——而是建立 TCP 连接、握手等的成本。

如果你可以在一个连接上做很多工作,那比每次都建立一个新的连接更有效。用现实世界的术语来说,考虑两个人之间的电话交谈。

高效场景:你拨打号码,他们接听,你说话,他们回复,你说话,他们回复等。

低效场景:你拨号码,他们接听,你说话,他们回复,你挂断。然后您立即再次拨打该号码,他们接听,您说话,他们回复,您挂断等。

想象一下在现实中做后者!你很快就会发疯...

编辑:默认情况下,WebClient将打开一个挂起的连接到 Web 服务器。如果您强制重置连接(基本上禁用 KeepAlive),那么您将再次看到缓慢的行为。

于 2010-02-19T13:12:57.933 回答
1

每个 TCP 连接在创建时都需要握手(公平的三向握手,不确定 atm),这意味着即使没有发送数据但将一个包发送到目标,也会发回另一个包 - 如果它是三向握手 - 第三个被发送到目标。

假设一个包裹从英国到日本的时间为 100 毫秒。这意味着每个“tcpClient.Connect()”需要 300 毫秒而不发送任何数据。您的正常发送和接收包括一个包裹发送到目的地,另一个包裹返回,总共需要 200 毫秒。关机(如果它是干净的)需要另外 100 毫秒。

这导致发送消息需要 600 毫秒,相比之下,如果您保持连接正常,则需要 200 毫秒,因为您将保存握手并关闭。

于 2010-02-19T13:15:19.053 回答