为了账号安全,请及时绑定邮箱和手机立即绑定

UDP SetWriteBuffer 和 SetReadBuffer 如何处理操作系统的缓冲区?

UDP SetWriteBuffer 和 SetReadBuffer 如何处理操作系统的缓冲区?

Go
慕无忌1623718 2022-05-23 15:02:01
描述我正忙着用 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 1024l, err := s.socketSim.Read(buffer)这工作正常,我停止收到错误......但是,我可以跨net包内的两个函数:s.socketSim.SetWriteBuffer(64 * 1024 * 1024)s.socketSim.SetReadBuffer(64 * 1024 * 1024)我了解到这两个作用于operating system's transmit buffer问题我是否关心设置操作系统缓冲区大小,为什么?应用程序缓冲区的大小如何影响操作系统缓冲区的大小?它们是否应该始终相同,它们应该/可以变得多大?
查看完整描述

1 回答

?
慕莱坞森

TA贡献1810条经验 获得超4个赞

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

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

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

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

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

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


查看完整回答
反对 回复 2022-05-23
  • 1 回答
  • 0 关注
  • 252 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号