【问题标题】:Reasonable amount of data to be send via single send call通过单次发送调用发送合理数量的数据
【发布时间】:2014-09-05 20:56:22
【问题描述】:

我需要通过 TCP 套接字向其他客户端发送不同大小的文件。现在我想知道一次发送函数调用多少数据是合理的?

例如,我不会发送带有 1 次发送调用的整个 2 兆字节的图片 - 我会将该文件分割成更小的缓冲区并一个接一个地发送。但是这些缓冲区应该多小或多大呢?我知道 send 并不能保证发送我的所有数据 - 我会检查一下。

【问题讨论】:

  • 最大以太网 MTU? 1500 字节

标签: c windows send


【解决方案1】:

这并不重要,只要您发送的缓冲区大于 MTU(通常略低于 1500 字节左右)。如果您发送大于 MTU 的缓冲区,操作系统或 NIC 会将您的数据包分段为 MTU 大小的数据包,您无需担心自己进行分段。发生这种情况时,操作系统将阻止对 send() 的调用,直到所有数据都已发送或发生错误 - 如果需要,您可以在一次调用中发送所有 2 MB,这不会有问题。

如果只是由于缓存效应(即由于数据并非全部都适合 L2 缓存,您将有更多的缓存未命中,那么您可能会在调用非常大的调用与仅比 MTU 大的调用时获得稍差的性能),但这可能不是很重要。

但是,对于文件传输,如果您使用TransmitFile() 函数,而不是手动将文件中的数据读取到缓冲区然后发送,您实际上会获得更好的性能。该功能针对文件传输进行了高度优化,因为它可以将文件数据直接从文件系统 DMA 到 NIC,而无需将其从内核空间复制到用户空间,然后再复制回内核空间。这称为zero-copy operation

【讨论】:

  • Stevens 在他的书中讨论了这个主题:Unix 网络编程。这个想法是发送足够多的来填充 OS 缓冲区而不是更多是理想的,因为它会减少系统调用和从用户空间到内核空间的转换次数。
  • 哦,哇,我不知道内核会砍掉我的文件并处理它。非常感谢您对 TransmitFile 函数的建议,但它可以同时返回已经发送的字节数吗?因为我需要做一个进度条。或者例如,假设我想通过单个发送调用发送 50 兆字节的文件,那么我也将无法同时接收发送的字节,对吗?这就是为什么我想自己切文件并发送小缓冲区以便我可以轻松地编写进度条。或者也许有一个使用 TRansmitFile 函数的解决方案?
【解决方案2】:

执行send() 的线程的响应性决定了通过单个send() 调用发送的数据大小

    1234563在这种情况下,发送()调用不会返回,直到整个数据被发送,因此您的线程无法响应/执行任何其他操作。
  1. 另一方面,如果您希望执行 send() 的线程具有响应性,您需要将数据分解为更小的缓冲区。这样,您的线程在每个部分缓冲区的 send() 之后获得执行时间。缓冲区的大小应直接取决于您拥有的数据速度,并与预期的响应速度成反比。

【讨论】:

  • 这正是我的想法。我想自己将文件切入缓冲区并在每个之后发送,这样我也可以制作进度条,但我会等待亚当的更多信息。
猜你喜欢
  • 1970-01-01
  • 2020-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多