Runtime: Add a Socket.Listen() overload

Created on 25 Jun 2016  ·  10Comments  ·  Source: dotnet/runtime

Edited by @stephentoub 3/12/2019:
Proposal:
```C#
namespace System.Net.Sockets
{
public class Socket
{
...
public void Listen(); // new overload
public void Listen(int backlog); // existing overload
...
}
}

[`Socket.Listen`](https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.listen%28v=vs.110%29.aspx) requires an `int backlog` parameter. Please add an overload that chooses a good default value.
1. Almost nobody seems to know what's a good value to pass here. Nobody takes the time to test this.
2. So far I have never seen a practical case where the value mattered.
3. I'm not even sure to what extent the different operating systems use that value. I know for sure that some do not allow certain ranges of values and override.

Quoting [MSDN `listen` documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ms739168%28v=vs.85%29.aspx):

> The maximum length of the queue of pending connections. If set to SOMAXCONN, the underlying service provider responsible for socket s will set the backlog to a maximum reasonable value. If set to SOMAXCONN_HINT(N) (where N is a number), the backlog value will be N, adjusted to be within the range (200, 65535). Note that SOMAXCONN_HINT can be used to set the backlog to a larger value than possible with SOMAXCONN.
> SOMAXCONN_HINT is only supported by the Microsoft TCP/IP service provider. There is no standard provision to obtain the actual backlog value.

I suggest this:

void Listen() => Listen(int.MaxValue);
```

Because this is what TcpListener.Start() does. Probably, every interesting OS replaces that with "a maximum reasonable value".

SOMAXCONN is int.MaxValue anyway. This seems to trigger the dynamic backlog feature of Windows server OS'es.

Note, that TcpListener.Start(int backlog) does different argument validation than Socket.Listen(int backlog) does. Might be worth investigating and unifying. But that's not what this ticket is about.

Surveying what .NET internal code passes:

  1. FTP uses 1 for it's active channel. Seems unsafe since a spurious connect (port scan) could kill the connection.
  2. WCF uses if (OSEnvironmentHelper.IsApplicationTargeting45) return (12 * OSEnvironmentHelper.ProcessorCount); else return 10;. Seems like they made a mistake here and fixed it. 10 clearly is not an appropriate value for a webservice with unknown load profile. I think the new computation is not good, either. They should just pass int.MaxValue.

I suggest marking this issue as available for community contribution.

api-approved area-System.Net.Sockets

Most helpful comment

@madenwala is working on this one.
cc: @danmosemsft, FYI.

All 10 comments

cc: @CIPop @himadrisarkar

I have similar issues with that parameter, maybe comments (related to Windows Server 2012r2) would be useful.

Almost nobody seems to know what's a good value to pass here. Nobody takes the time to test this.

See my case with FTP here, when there are more than 1k connections at the same time the default backlog limit on Windows Server 2012r2 is not enough.

So far I have never seen a practical case where the value mattered.

Important to avoid 'Connection refused' error during connection burst when few hundred connections trying to establish link at the same time.

I'm not even sure to what extent the different operating systems use that value. I know for sure that some do not allow certain ranges of values and override.

Did some investigations while having an issue with backlog limit with FTP.
If set to SOMAXCONN Windows Server since 2008 uses 200 and there is no way to override this except using of SOMAXCONN_HINT which is just a macro that converts value into negative form.
proof in the comments

I don't believe there is a "generic" backlog number for listen. In my opinion, the best way to determine it is to run a stress test on your application running on the destination hardware.
You may want to set the backlog to the maximum number of connections that your application can actually handle under stress. It's a good idea to reject connections immediately and potentially redirect client requests to other servers via some type of load balancing device or protocol (e.g. DNS).

I'm also forwarding this question internally to Winsock owners in case I'm missing something and will follow-up with their answers.

Well, the kernel does expose a generic number (SOMAXCONN). I believe many applications use that, or something equivalent (enough) to that such as 0 or int.MaxValue. This already is a reality. Given that the backlog, I think, rarely matters in practice I think this is the safest default choice. It just makes all problems go away.

Usually, applications accept connections in a tight loop anyway. They are not doing processing synchronously. That's further evidence the backlog is moot and should just not be a concern.

This already is a reality. Given that the backlog, I think, rarely matters in practice I think this is the safest default choice. It just makes all problems go away.

I agree, since it's not easy or even feasible to run the perf tests and obtain the limits for a particular hardware.
We could just add the overload w/o the int param to the next version of the contract and default to SOMAXCONN. (Still waiting for the TCP Team's answer.)

The TCP Team's answer is inline with @GSPP's request and solution:

The general recommendation is “As high as needed to allow for time to process bursts of inbound connections.” In practice most people just specify SOMAXCONN and call it a day (and keep their AcceptEx code path as thin and lock-free as possible).

We extended this with the _HINT option for servers handling huge bursts of connections, where a couple hundred in a backlog depth just wasn’t enough, and these servers had more than enough physical memory to handle the bursts in non-paged pool for these pended connections.

The primary scenario/workload for which SOMAXCONN_HINT was needed is the case where a cluster of >=1000 machines trying to establish full mesh connectivity to each other (during cluster start-up).

Assigning this to @himadrisarkar for scheduling.

If someone wants to pick this up sooner, please follow https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md

Video

Makes sense.

@madenwala is working on this one.
cc: @danmosemsft, FYI.

fyi, for Linux, from listen.

       If the backlog argument is greater than the value in
       /proc/sys/net/core/somaxconn, then it is silently truncated to that
       value; the default value in this file is 128.
Was this page helpful?
0 / 5 - 0 ratings