【发布时间】:2014-09-05 20:56:22
【问题描述】:
我需要通过 TCP 套接字向其他客户端发送不同大小的文件。现在我想知道一次发送函数调用多少数据是合理的?
例如,我不会发送带有 1 次发送调用的整个 2 兆字节的图片 - 我会将该文件分割成更小的缓冲区并一个接一个地发送。但是这些缓冲区应该多小或多大呢?我知道 send 并不能保证发送我的所有数据 - 我会检查一下。
【问题讨论】:
-
最大以太网 MTU? 1500 字节
我需要通过 TCP 套接字向其他客户端发送不同大小的文件。现在我想知道一次发送函数调用多少数据是合理的?
例如,我不会发送带有 1 次发送调用的整个 2 兆字节的图片 - 我会将该文件分割成更小的缓冲区并一个接一个地发送。但是这些缓冲区应该多小或多大呢?我知道 send 并不能保证发送我的所有数据 - 我会检查一下。
【问题讨论】:
这并不重要,只要您发送的缓冲区大于 MTU(通常略低于 1500 字节左右)。如果您发送大于 MTU 的缓冲区,操作系统或 NIC 会将您的数据包分段为 MTU 大小的数据包,您无需担心自己进行分段。发生这种情况时,操作系统将阻止对 send() 的调用,直到所有数据都已发送或发生错误 - 如果需要,您可以在一次调用中发送所有 2 MB,这不会有问题。
如果只是由于缓存效应(即由于数据并非全部都适合 L2 缓存,您将有更多的缓存未命中,那么您可能会在调用非常大的调用与仅比 MTU 大的调用时获得稍差的性能),但这可能不是很重要。
但是,对于文件传输,如果您使用TransmitFile() 函数,而不是手动将文件中的数据读取到缓冲区然后发送,您实际上会获得更好的性能。该功能针对文件传输进行了高度优化,因为它可以将文件数据直接从文件系统 DMA 到 NIC,而无需将其从内核空间复制到用户空间,然后再复制回内核空间。这称为zero-copy operation。
【讨论】:
执行send() 的线程的响应性决定了通过单个send() 调用发送的数据大小
另一方面,如果您希望执行 send() 的线程具有响应性,您需要将数据分解为更小的缓冲区。这样,您的线程在每个部分缓冲区的 send() 之后获得执行时间。缓冲区的大小应直接取决于您拥有的数据速度,并与预期的响应速度成反比。
【讨论】: