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

时间:2019-12-06 15:31:22

标签: c++ sockets networking

我不时看到旧版源代码中与网络相关的代码,并且在其他地方修改了套接字的接收缓冲区大小(使用setsockoptSO_RCVBUF选项)。在我的Windows 10系统上,套接字的默认缓冲区大小似乎是64kB。我现在正在使用的旧代码(写在10年前)将每个套接字的接收缓冲区大小设置为256kB。

与此相关的一些问题:

  1. 在监视和连续读取套接字时,是否有任何理由修改接收缓冲区的大小,例如使用select
  2. 如果没有,那么10年前有没有动力?
  3. 是否有任何示例,用例或应用程序,需要修改套接字的接收缓冲区大小(甚至发送缓冲区大小)?

2 个答案:

答案 0 :(得分:3)

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

是否需要执行此操作取决于两个因素:期望数据填充套接字的接收缓冲区的速度有多快,应用程序通过调用recv()耗尽套接字的接收缓冲区的速度有多快。如果应用程序能够可靠地耗尽缓冲区的速度快于接收数据的速度,则默认缓冲区大小就可以了。 OTOH如果您发现并非总是能够做到这一点,那么较大的接收缓冲区大小可能会帮助它更优雅地处理传入数据的突然突发。

  

套接字时是否有任何理由修改接收缓冲区的大小   被监视并连续读取,例如使用选择吗?

如果传入的数据速率很高(例如每秒兆字节,甚至只是偶尔的数据突发速率),或者线程在select()/ recv()调用之间做某事可能会长时间保持忙碌-例如如果线程曾经需要写入磁盘,则在某些情况下,磁盘写入调用可能需要几百毫秒,这可能会在此期间允许套接字的接收缓冲区填满。

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

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

答案 1 :(得分:1)

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

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

小型RECVBUF在低延迟网络上可以很好地工作,但是在高带宽高延迟网络上,ACKS可能需要很长时间才能到达发送方,并且由于发送方窗口已用完,因此发送方将无法利用全部带宽。

增加RECVBUF大小会增加窗口,这意味着发送方可以在等待ACK的同时发送更多数据,这将使发送方可以利用整个带宽。这确实意味着事情反应迟钝。

缩小RECVBUF意味着发送方的响应速度更快,并且知道接收方没有吃掉数据,并且可以更快地回退。

相同的逻辑也适用于SENDBUF。

相关问题