一次性将 GB 字节写入 TCP 套接字是一种好习惯吗?

问题描述

我正在维护一些通过 TCP 套接字发送数据的成熟生产代码。它总是将大块数据分成许多数据包,每个数据包 1000 字节。我只是想知道为什么要这样做。为什么我不能一次性将一个 GB 的字节数组写入套接字?这样做有什么缺点?

解决方法

根据底层实现,尝试批量发送 1GB 可能会导致 1GB 被复制到某个缓存中,然后在那里保留一段时间。因此,如果没有足够的可用内存(即使有足够的可用内存 - 这可能不是利用它的最有效方式),这可能是一个问题。

虽然“手动”将其分成 1000 个字节的段,但对我来说听起来有点矫枉过正。

,

有很多理由不要一次投入一大块。

首先:即使在非常快的网络上发送一 GB 数据也需要很长的时间。在 10Gbps 网络上,它需要不到 1 秒的时间,这在计算机语言中是很长的时间。并且假设这一项操作拥有网络的所有可用带宽,并且不必与其他任何东西共享。

这意味着,如果您成功地对 TCP 套接字进行了 1GB write 调用,则需要一段时间才能真正发送后面的数据位。

同时,您必须将所有数据保存在内存中。这意味着您需要为整个事务分配并保留 1GB 的数据。

如果您在每次写入之前填充一个小缓冲区并从源中读取(或生成,取决于数据的来源),那么您将只需要一点内存(缓冲区的大小)。

对于今天的机器来说,所有这些听起来可能没什么大不了的,但考虑到许多服务器将同时为数百个客户端/请求提供服务,如果每个服务器都需要 1GB 的缓冲区,那么这可能会很快失控。

1000 是否适合该缓冲区的大小?我不是网络专家,但我怀疑这有点低。也许 64k 左右的东西是合适的,但其他人可以在这里提供更好的细节。找到合适的缓冲区大小有时会有点棘手。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...