描述

我正在用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


我什至不愿意设置操作系统缓冲区大小,为什么?应用程序缓冲区的大小如何影响操作系统缓冲区的大小?它们应该始终相同,应该/可以变成多大?

最佳答案

首先,您不仅为设备上的每个接口以及从其发送/接收的任何目的地都设置了MTU大小,而且在这两者之间还为每个设备设置了MTU大小。因此,正如其他人提到的那样,您可能希望使用MTU普遍接受的功能,因为您可能无法控制数据路由中的每个设备。对于UDP,MTU实际上只是表示分段之前一个数据报可以有多大。

其次,您几乎可以肯定希望SND / RCV缓冲区大于MTU。这些是内核缓冲区,可在您不准备接收数据时保留这些数据。较大的UDP RCV缓冲区意味着内核将为您缓冲更多的数据包,然后再将其丢入深渊。也许您需要为每个数据包做一些不平凡的工作。根据比特率,您可能需要更大或更小的内核缓冲区。

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

或者,如果知道定时不确定,则如果丢弃的数据包不可接受,则可以考虑使用TCP。

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

另外,您可以通过监视/ proc / net / udp中的数据包丢弃来调整缓冲区大小。如果看到丢弃,则可能需要增大rcv缓冲区,尤其是在数据突发且处理密集的情况下。如果数据以一致的速率传入,而您仍在丢弃数据包,则说明处理速度不够快。

关于sockets - UDP SetWriteBuffer和SetReadBuffer如何在OS的缓冲区中使用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60675255/

10-13 09:33