使用TCP,为什么大块数据的带宽传输速率比小块数据低?

3
使用两台安装有Windows XP的电脑,64kB的TCP窗口大小,使用交叉线连接
使用Qt 4.5.3,QTcpServer和QTcpSocket

发送2000个40kB的消息需要2秒钟(40MB/s)
发送1个80MB的消息需要80秒钟(1MB/s)

有人能解释一下吗?我本来以为较大的消息会更快,因为低层可以更有效地填充TCP数据包。

数据大小小于64KB的将直接通过,而大于64KB的数据将被分成64KB的块进行传输,这个过程需要更多的时间来拆分和合并数据,因此需要更长的时间。 - Badr
@moon:胡说八道。你分割任务节省的时间都会在打开太多连接时的网络延迟中浪费掉。 - Billy ONeal
@Pieter:如果您使用本机套接字设施而不是Qt提供的设施,行为是否仍然发生? - Billy ONeal
@Billy 好主意。如果这是QT的bug,我不会感到惊讶——因为这并不是第一次出现。 - BЈовић
无论是Qt还是操作系统都肯定存在问题。我在QTcpSocket :: write周围包装了一个函数,将所有消息分成40kB的块。现在我的所有数据以大约40MB / s的速率发送。找到原因的人将获得奖励 :) - Pieter
我向Qt报告了此问题,显然他们在4.5.3和4.7之间更改了缓冲区的管理方式。 - Pieter
3个回答

2

没有看到你的代码,很难对此进行评论。

你是如何在发送端计时的?你何时知道完成了?

客户端如何读取数据?它是否读入固定大小的缓冲区并丢弃数据,还是从帧中(通过分帧)得知“消息”大小为80MB,并尝试将“消息”组合成单个数据缓冲区传递给应用程序层?

这不太可能是底层的Windows sockets代码导致性能差。


1

TCP从应用程序端是基于流的,这意味着没有数据包,只有一系列字节。内核可能在发送之前收集多个连接写入,并且接收方可以使任何数量的接收数据对每个“读”调用可用。

TCP,在IP侧,是数据包。由于标准以太网具有1500字节的MTU(最大传输单元),而TCP和IP都有20字节的头,因此通过以太网传输的每个数据包将向另一侧传递1460字节(或更少)的TCP流。应用程序的40KB或80MB写入在这里没有任何区别。

数据传输需要多长时间取决于您如何测量以及在何处测量。写入40KB可能会立即返回,因为该数据量将简单地放置在内核中TCP的“发送窗口”中。 80MB的写入将阻塞等待所有数据被传输(除了最后的64KB,它将在窗口中适合挂起)。

TCP传输速度也受接收方的影响。它有一个“接收窗口”,其中包含从对等方接收但应用程序尚未获取的所有内容。每次返回ACK时,将可用空间量传递给发送方,因此如果接收应用程序未能快速清空该窗口,则发送方最终会暂停。WireShark可能在这里提供一些见解。
最终,两种方法应该在相同的时间内传输相同的数据量,因为无论如何切分数据,应用程序都可以轻松地比TCP更快地填充传出窗口。
我无法代表QT的操作发表评论。

Qt在其之上构建了一个框架,您可以在此处找到更详细的解释:https://dev59.com/KlDTa4cB1Zd3GeqPLKwx - Pieter

-1

Qt 4.5.3 中的 Bug

..................................


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接