在UDP套接字上即时更改SOL_SOCKET,SO_RCVBUF的可预期行为是什么? [英] What is the predictable behavior of changing SOL_SOCKET, SO_RCVBUF on the fly on a UDP socket?

查看:62
本文介绍了在UDP套接字上即时更改SOL_SOCKET,SO_RCVBUF的可预期行为是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What should be expected to happen if we resize the input buffer of a UDP server socket on the fly on a Linux system?

setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ...)

我对这些问题特别感兴趣:

I am particularly interested in these questions:

  • 如果我缩小到缓冲区中当前的大小以下,这会简单地删除最旧/最新的吗?数据报是否正确,或者是否可以刷新其中的所有内容,或更糟的是它会破坏数据,例如截断数据报?
  • 缩小缓冲区会节省内存还是会阻止内存被系统重用?
  • 该行为是否可以预测或有时会随机出现?

推荐答案

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

First and foremost: the term "buffer" might be confusing: the kernel does not actually save packets in buffers of fixed size, but rather in queues called "backlogs" (see include/net/sock.h:400). The size set through SO_RCVBUF and SO_SNDBUF only limits the maximum size of the backlog.

如果我缩小到缓冲区中当前的大小以下,是否会简单地删除最早/最新的内容?

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

否,保留已收到的内容.没有数据报被丢弃.当您执行 setsockopt(SO_RECVBUF)时,唯一发生的事情是

No, what was already received is kept. No datagrams are thrown away. The only thing that happens when you do setsockopt(SO_RECVBUF) is that the value of the sk_rcvbuf field of the socket is changed. No other action is performed.

只有在接收到更多数据包时才能看到其真正的效果:接收到的所有后续数据报将被立即丢弃,并将继续丢弃,直到队列缩小到设置的大小以下(即用户空间接收到足够的数据报)为止.

The real effect of this is only seen when receiving more packets: all subsequent datagrams that are received will be immediately dropped, and will continue being dropped until the queue shrinks under the set size (i.e. userspace receives enough datagrams).

缩小缓冲区会节省内存还是会阻止内存被系统重用?

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

正如我之前所说,由于缓冲区"并不是真正的缓冲区,并且没有固定的大小,更改 SO_RECVBUF 不会立即更改任何内容.

As I said earlier, since the "buffer" is not really a buffer and does not have a fixed size, changing SO_RECVBUF will not change anything immediately.

有两种情况:

  1. 如果未完成订单的大小小于或等于指定的大小:新的最大大小将受到限制,因此将来将在处保存内存可能丢失数据包的成本.
  2. 如果待办事项大小超过指定的大小:当用户空间接收到缓冲的数据包时,内存最终将被释放,并且不会再次超出设置值.将来会再次节省内存.
  1. If the backlog size was below (or equal to) the specified size: the new maximum size will be limited, so it will save memory in the future at the cost of potentially losing packets.
  2. If the backlog size was above the specified size: memory will eventually be freed when userspace receives the buffered packets, and it will not grow again over the set value. This will again save memory in the future.

行为是可以预测的还是有时会随机出现?

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

看看内核代码,我会说以我上面描述的方式是100%可预测的.但是,我不确定这在哪里记录.我想说的是,如果您考虑发送和接收缓冲区"消息,这是很直观的.作为队列(实际上是队列).

Looking at the kernel code, I would say 100% predictable in the way I described above. However I am not entirely sure where this might be documented. I would say it's kind of intuitive if you think about send and receive "buffers" as queues (which they actually are).

这篇关于在UDP套接字上即时更改SOL_SOCKET,SO_RCVBUF的可预期行为是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆