-
-
Notifications
You must be signed in to change notification settings - Fork 392
Description
Before I looked into it, my assumption was that we should default SO_REUSEADDR to enabled. But it turns out that things are more complicated than that.
The situation as I understand it:
On Unix:
- For clients,
connecton an unbound socket will automatically pick a good port + interface, and part of picking a "good" one is that it knows who you're connecting to, so it can strategically re-use local ports. (It's okay to have two client connections use the same local port so long as the peers have different addresses.) - For servers,
bindwill by default disallow re-use of ports that are in TIME_WAIT, which is generally considered over-fussy these days. So generally it's recommended to enableSO_REUSEADDR, which allows to bind to ports that are in TIME_WAIT but otherwise unused. - For clients that call
bindbeforeconnect, you probably don't want to useSO_REUSEADDR, because it makes it possible to get a port that ends up failing when you callconnect(ref). Though really you're best off not callingbindat all, becauseconnectcan do a better job ofbinding than you can, because it has more information at hand. [Edit: on recent Linux there's alsosock.setsockopt(IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, 1); sock.bind((host, 0))which means "bind me to this host, but delay picking the port until I callconnect.]
On Windows:
- For clients, the plain
connectfunction acts similar to Unix, AFAIK. (The WSA-level functions likeConnectExare different and require you tobindfirst, but ATM we aren't using those.) - For servers, you have to enable
SO_EXCLUSIVEADDRUSEor else any program with the same uid can hijack your port. (Yes! At least this is better than it used to be – in XP and earlier, they didn't even have the uid check.) This is also required to prevent weird problems like being allowed to bind to a wildcard address + port where there is already another program bound to that port on all the concrete addresses. However, the downside is that it also prevents re-using ports that are in TIME_WAIT. - Never ever ever use
SO_REUSEADDR, it's totally broken
(Reference for the delightful Windows behavior)
So one option would be to default-enable SO_REUSEADDR on Unix and SO_EXCLUSIVEADDRUSE on Windows. I'm a bit concerned about whether this will have a negative effect on clients, though – maybe we only want this to be the default for listening sockets? That's trickier. I guess we could set it in bind if not overridden? Or maybe we should keep it simple and say that it's default-enabled, and if you want to turn it off again then go for it.
Also, we should probably just not even expose SO_REUSEADDR on Windows, b/c it is a massive trap. Or even make trying to access it raise AttributeError: no really you don't want this, see <link>.