sockets - 在UDP套接字上即时更改SOL_SOCKET,SO_RCVBUF的可预期行为是什么?

标签 sockets networking linux-kernel udp setsockopt

如果我们在Linux系统上即时调整UDP服务器套接字的输入缓冲区的大小,将会发生什么?

setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ...)
我对以下问题特别感兴趣:
  • 如果我缩小到缓冲区中当前的大小以下,是否会简单地删除最旧/最新的?数据报是否正确,或者是否可以刷新其中的所有内容,或更糟的是它会破坏数据,例如截断数据报?
  • 缩小缓冲区甚至会节省内存还是会阻止该内存被系统重用?
  • 行为是可预测的还是有时会随机出现?
  • 最佳答案

    首先,术语“缓冲区”可能令人困惑:内核实际上并未将包保存在固定大小的缓冲区中,而是保存在称为“积压”的队列中(请参阅 include/net/sock.h:400 )。通过SO_RCVBUFSO_SNDBUF设置的大小仅限制了积压的最大大小。

    If I shrink below what is currently in the buffer, would this simply drop the oldest/newest?


    不,保留已收到的内容。没有数据报被丢弃。当您执行setsockopt(SO_RECVBUF)时,唯一发生的就是the value of the sk_rcvbuf field of the socket is changed。不会执行其他任何操作。
    仅当接收到更多数据包时才能看到此操作的实际效果:接收到的所有后续数据报将被立即丢弃,并将继续丢弃,直到队列缩小到设置的大小以下(即用户空间接收到足够的数据报)为止。

    Would shrinking the buffer even save memory or something prevents that memory from being reused by the system?


    如前所述,由于“缓冲区”实际上不是缓冲区,并且没有固定大小,因此更改SO_RECVBUF不会立即更改任何内容。
    有两种情况:
  • 如果待办事项大小小于(或等于)指定的大小:新的最大大小将受到限制,因此它将在将来节省内存,但有可能丢失数据包。
  • 如果待办事项大小大于指定的大小:当用户空间接收到缓冲的数据包时,最终将释放内存,并且内存将不会再次超过设置的值。将来会再次节省内存。

  • Is the behavior predictable or could it behave randomly at times?


    看一下内核代码,我会说以我上面描述的方式是100%可预测的。但是,我不确定这在哪里记录。我想说的是,如果您考虑将“缓冲区”作为队列发送(实际上就是队列),那是一种直观的感觉。

    关于sockets - 在UDP套接字上即时更改SOL_SOCKET,SO_RCVBUF的可预期行为是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64523733/

    相关文章:

    azure - 无法检索subnet_Id - Terraform

    linux-kernel - Linux 调度器

    安卓套接字代码

    sockets -/etc/init.d 中缺少 mysqld.sock 和 mysqld

    c - 使用 Unix 套接字获取 "Address already in use"错误

    java - 单独的线程和计时器一起工作

    mysql - 无法连接到在不同计算机上的容器上运行的远程 mySQL 数据库

    networking - NS2:链接的随机延迟

    linux - 设备映射器的“ioctl”签名

    linux - 我该如何解决警告 DEPMOD