Why listen(2)
's backlog parameter has such an odd meaning
In light of what the listen(2)
backlog parameter actually means, ie very little, you might sensibly wonder why
it has such an odd and basically useless definition. For instance, it
might be quite useful to be able to put a real limit on the number of
TCP connections that have been fully established but not accept()
'd by
your server.
The simple answer is that the listen(2)
backlog is not about helping
your program out, it is about limiting how many kernel resources can be
(invisibly) consumed by connections that haven't yet been accept()
'd
and surfaced in your program (and limited, if only by file descriptor
limits). Such connections are basically invisible to normal tools,
programs, and Unix limits because they haven't yet been materialized
as file descriptors and exist only in the depths of the kernel socket
stack. This means that the kernel needs to limit them somehow. In theory
the kernel could have applied the same limit to everything and not
provided any way for applications to change it. In practice, I suspect
that the early developers of BSD wanted to allow a way for some select
daemons they expected to be unusually active to raise the normal limit
(and perhaps for very inactive daemons to lower it to save kernel
memory).
This leads to a simple but not particularly useful rule for what the
listen(2)
backlog actually limits: anything that your kernel thinks
uses enough resources to care about. And this has changed over time.
As kernels have found clever ways to handle various things that have
traditionally consumed resources (such as half-open TCP connections),
they've stopped counting against the backlog limits. Some of this
evolution has been driven by necessity (such as people on the Internet
exploiting half-open TCP connections as one of the first denial of
service attacks) and some of it has simply been driven by the cleverness
of kernel programmers. This has led to the current situation where
understanding the effects of any specific backlog requires knowing
something about the kernel implementation of the specific socket type
involved and what things in it do and don't use up kernel resources.
(See also Derrick Petzold's somaxconn - That pesky limit, which has some interesting quotes from Stevens' Unix Network Programming.)
|
|