何时需要修改套接字的接收缓冲区大小?



我不时在遗留源代码和其他地方看到与网络相关的代码修改套接字的接收缓冲区大小(使用带有SO_RCVBUF选项的setsockopt(。在我的 Windows 10 系统上,套接字的默认缓冲区大小似乎是 64kB。我现在正在处理的遗留代码(编写于 10+ 年前(将每个套接字的接收缓冲区大小设置为 256kB。

与此相关的一些问题:

  1. 当套接字被监控和连续读取时,例如使用select时,是否有任何理由修改接收缓冲区大小?
  2. 如果没有,10+年前是否有一些动机?
  3. 是否有任何示例、用例或应用程序需要修改套接字的接收缓冲区大小(甚至发送缓冲区大小(?

通常,接收缓冲区大小被修改为更大,因为代码的作者试图降低套接字的接收缓冲区已满的情况的可能性,因此操作系统必须丢弃一些传入数据包,因为它没有地方放置数据。 在基于 TCP 的应用程序中,这种情况将导致流暂时停止,直到成功重新发送丢弃的数据包;在基于 UDP 的应用程序中,这种情况将导致传入的 UDP 数据包以静默方式丢弃。

是否有必要这样做取决于两个因素:数据填满套接字接收缓冲区的速度,以及应用程序通过调用套接字recv()耗尽套接字接收缓冲区的速度。 如果应用程序能够可靠地以比接收数据更快的速度耗尽缓冲区,则默认缓冲区大小很好;OTOH 如果您发现它并不总是能够这样做,那么更大的接收缓冲区大小可能有助于它更优雅地处理突然爆发的传入数据。

套接字时是否有任何理由修改接收缓冲区大小 被监控和连续读取,例如使用 SELECT?

如果传入数据速率很高(例如每秒兆字节,甚至只是偶尔以该速率突发数据(,或者线程在select((/recv((调用之间执行某些操作可能会使其在相当长的一段时间内保持忙碌 - 例如,如果线程需要写入磁盘, 在某些情况下,磁盘写入调用可能需要几百毫秒,可能允许套接字的接收缓冲区在此期间填充。

对于非常高带宽的应用程序,即使是非常短的暂停(例如,由于线程从CPU中启动了几个量子,以便另一个线程可以运行一两个量子(也足以允许缓冲区填满。 这在很大程度上取决于应用程序的用例,当然也取决于CPU硬件相对于网络的速度。

至于何时开始弄乱接收缓冲区大小:除非您注意到应用程序丢弃了足够的传入数据包,以至于明显限制了应用程序的网络性能,否则不要这样做。 分配比您需要的更多的 RAM 是没有意义的。

对于 TCP,RECVBUF 缓冲区是内核可以容纳的最大未读字节数。在 TCP 中,窗口大小反映了发送方可以安全发送的最大未确认字节数。发件人将收到一个 ACK,其中包含一个新窗口,该窗口取决于 RECVBUF 中的可用空间。

当 RECVBUF 已满时,发送方将停止发送数据。由于机制意味着发送方将无法发送比接收应用程序可以接收的更多的数据。

小型 RECVBUF 在低延迟网络上运行良好,但在高带宽高延迟网络上 ACKS 可能需要很长时间才能到达发送方,并且由于发送方已用完窗口,发送方将不会使用全部带宽。

增加 RECVBUF 大小会增加窗口,这意味着发送方可以在等待 ACK 时发送更多数据,这将允许发送方利用整个带宽。这确实意味着事情的响应速度较慢。

缩小 RECVBUF 意味着发送方响应更快,并且知道接收方不会吃掉数据,并且可以更快地后退。

同样的逻辑也适用于SENDBUF。

最新更新