【问题标题】:How does UDP SetWriteBuffer and SetReadBuffer the OS's buffers?UDP SetWriteBuffer 和 SetReadBuffer 如何处理操作系统的缓冲区?
【发布时间】:2020-03-13 18:00:24
【问题描述】:

说明

我正忙着用 Go 编写一个高频 UDP 服务器。我估计两种方式至少每秒 1000 个数据包。

但是,随着我通过 UDP 套接字发送的数据大小增加,我最终遇到了以下错误:read udp 127.0.0.1:1541->127.0.0.1:9737: wsarecv: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself.

我最终只是增加了我正在读取和写入的缓冲区的大小,如下所示:

buffer := make([]byte, 64 * 1024 * 1024) // used to just be 1024
l, err := s.socketSim.Read(buffer)

这工作正常,我停止收到错误...但是我可以跨 net 包内的两个函数:

s.socketSim.SetWriteBuffer(64 * 1024 * 1024)
s.socketSim.SetReadBuffer(64 * 1024 * 1024)

我了解到这两个作用于operating system's transmit buffer

问题

我是否关心设置操作系统缓冲区大小,为什么?应用程序缓冲区的大小如何影响操作系统缓冲区的大小?它们是否应该始终相同,它们应该/可以变得多大?

【问题讨论】:

  • 您确定要首先编写大型 UDP 数据包吗?该规范将 UDP 帧大小限制为 65535,因此您实际上不能发送大于 65507(或 IPv6 IIRC 上的 65527)的有效负载。即便如此,这也需要在整个链路上支持巨型帧以防止分段(在大多数情况下为 44 个数据包,丢包的可能性是丢弃整个数据报的 44 倍)
  • 普遍接受的 UDP 数据报有效负载的实际限制是 534 字节。除此之外的任何事情都会导致 IP 碎片化,因此会增加丢包的风险。
  • 我宁愿避免丢包,也不愿使用更大的负载。所以我会根据规格保持尺寸。仍然有点困惑为什么我可以选择更改它......那么在哪种情况下大型 UDP 数据包是理想的?
  • @FanusduToit,当您控制网络并知道 MTU 时,大型 UDP 数据包工作得很好,因此它们不会分段。读写缓冲区不是数据包大小,它们只是用于读写的缓冲区,通常不需要设置。无论您将缓冲区设置为什么,您都不能在单个数据包中发送超过 65535 个字节,因为长度字段只有 16 位。
  • 例如,如果您正在构建一个在本地使用以太网巨型帧 (~9k) 的网络,并且您的 UDP 连接是纯本地的,那么您就知道可以发送 8KiB 的数据块因为他们只会进入一个巨型帧。设置这样的代码通常是明智的,以便您可以处理更常规的限制,但是,因为承诺的本地网络通常在销售人员接触它之后,不得不也可以在 WAN 空间玩 :-)

标签: sockets go udp buffer


【解决方案1】:

首先,您不仅有设备上每个接口的 MTU 大小以及您发送/接收的任何目的地的 MTU 大小,而且介于两者之间的每个设备也有一个 MTU 大小。出于这个原因,正如其他人所提到的,您可能希望使用 MTU 普遍接受的内容,因为您可能无法控制数据路由中的每个设备。在 UDP 的情况下,MTU 实际上只是表示数据报在分片之前可以有多大。

其次,您几乎肯定希望您的 SND/RCV 缓冲区大于 MTU。这些是内核缓冲区,当您还没有准备好接收数据时,它们会保留数据。更大的 UDP RCV 缓冲区意味着内核会在将它们放入深渊之前为您缓冲更多的数据包。也许您对每个数据包都有一些重要的工作要做。根据比特率,您可能需要更大或更小的内核缓冲区。

最后,您使用的是 UDP。无法保证您会按顺序或完全收到数据包。您和对等方之间的任何路由器都可能出于任何原因决定丢弃数据包。由于您使用的是 UDP,因此您应该为丢弃和乱序的数据包做好准备。您可能还需要某种重传机制,这会使事情变得更加复杂。

或者,如果丢弃的数据包不可接受,您可能会考虑使用 TCP,因为您知道时间是不确定的。

如果您使用的是 linux,您可以在 /proc/sys/net 中查看当前缓冲区大小。通常内核会加倍你的要求。

此外,您可以通过观察 /proc/net/udp 中的丢包情况来调整缓冲区大小。如果您看到下降,您可能希望使您的 rcv 缓冲区更大,特别是在数据是突发的和处理密集型的情况下。如果您的数据以一致的速率进入并且您仍在丢弃数据包,那么您处理它们的速度不够快。

【讨论】:

    猜你喜欢
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多