最小的SO_RCVBUF值是多少?

5
为了尽量减少延迟(我不关心数据包丢失),我希望UDP的接收缓冲区尽可能小。但是,当我将SO_RCVBUF设置为小于1000(使用setsockopt)时,我的程序就无法接收任何数据包。我发送的数据报有28字节的数据,总共在网络上传输的数据包大小为70字节,那么如果SO_RCVBUF小于1000,为什么我就无法接收任何数据呢?如何更改这个问题,以允许更小的缓冲区大小?
此外,是否可以按数据包数量而非字节数来设置缓冲区?或者是否有某种方法可以手动清空缓冲区?

6
为什么您认为减小接收缓冲区大小会降低延迟? - Nikolai Fetissov
@Nikolai 因为我处理每个数据包需要2毫秒,这期间其他任何数据包都只是在缓冲区中等待。所以如果两个数据包同时到达,其中一个将会增加2毫秒的延迟时间。 - Benubird
2
每次出队所有可用的数据包吗? - Nikolai Fetissov
1
非阻塞套接字,边缘触发的epoll或kqueue,在“可读”事件上读取直至获取EWOULDBLOCK。 - Nikolai Fetissov
@Nikolai,您能把您的评论发表为答案吗?这样我就可以接受它了。 - Benubird
显示剩余4条评论
3个回答

4
使套接字接收缓冲区更小并不能减少延迟。相反,您需要每次出列所有可用的数据包。这可以通过非阻塞套接字和边缘触发的epoll或kqueue实现 - 在"可读"事件上读取,直到获得EWOULDBLOCK。至于为什么使用小的SO_RCVBUF值时没有任何输入,请查看此处-http://vger.kernel.org/~davem/skb_sk.html,并在此处查看-http://lxr.linux.no/#linux+v2.6.37/include/net/sock.h#L621。希望这能有所帮助。

优秀的链接!不过,我认为所有数据包都会被复制到内核缓冲区中(其中SO_RCVBUFF确定了大小?)。那么,如果我们有一个非常大的SO_RCVBUFF,难道我们不会破坏缓存和TLB,从而产生更多的抖动和更高的延迟吗? - HCSF

0

这很可能是特定于平台的问题,所以你的目标平台是什么?

如果你正在使用Windows,则建议你使用重叠I/O和I/O完成端口,将接收缓冲区设置为0,并始终具有多个待处理的RecvFrom()调用。

这应该a)消除堆栈在没有RecvFrom()挂起时缓冲数据报的能力,b)允许您处理一些数据报。

然后,您可以调整挂起的重叠操作数量,使其始终比您拥有的内核数多几个,以处理传入的数据报,这样您就可以得到想要的结果。


0

你的问题没有意义。减小缓冲区大小并不能减少延迟。它只会增加传入数据报被丢弃的概率,如果套接字接收缓冲区没有足够的空间,就会发生这种情况。你关于两个同时传入的数据包的回答也没有意义。延迟是由处理传入数据的速度而不是缓冲区大小决定的。


数据包在从缓冲区读取之前不会被时间戳记,因此延迟(即发送和接收数据包之间的时间,如数据包时间戳值所示)部分取决于在缓冲区中花费的时间。丢失的数据包不计入平均延迟,因此较大的缓冲区由于更高的平均处理时间而产生更高的平均延迟。 - Benubird
2
在这种情况下,最好放弃每个数据包。您将拥有0毫秒的延迟。 - nos
@Benubird:这也没有意义。大缓冲区会产生更多的数据需要处理。在极限情况下,您可以拥有零缓冲区大小、零延迟和零数据需要处理。在某个地方,您必须接受延迟不是唯一需要优化的参数,并且减小套接字缓冲区大小基本上是不合理的。 - user207421
1
不,我正在尝试找到实际延迟的最佳近似值。如果数据包在缓冲区中等待1毫秒才被处理,那么数据包上的时间戳就是它到达后1毫秒。因此,为了更接近真实延迟,我希望尽量减少在缓冲区中停留的时间 - 这可以通过忽略任何未立即处理的数据包来实现。我也在优化其他所有内容。 - Benubird

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接