New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setsockopt(2) and reuse #861
Comments
@AngusL opens:
I don't know what this refers to. If anyone remembers, could we have a link to it? |
I'd never heard of that Windows option, so here's Microsoft's advice on using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE. Edited highlights:
So, AIUI, on Windows, multicast sockets where you want to share the port should have SO_REUSEADDR set, and all other sockets should have SO_EXCLUSIVEADDRUSE set. |
Personally, at the moment, i'm on UNIX, and i'd like to set SO_REUSEADDR on my multicast sockets. With the standard library as it stands, there's no way to do this, because sys_common::net::UdpSocket::bind goes straight from creating the socket to binding it:
I would love to have a way to set SO_REUSEADDR here, either specifically, or via a more general way to set options before binding. Meta-question: what is the bar to making changes to this code? If i come up with an idea that sounds okay and submit a PR, is there a chance it will be merged? Or does this need to go through some kind of process? Off the top of my head, i would suggest that the existing bind method becomes a method specifically for binding non-reusable sockets, and that both std::net::UdpSocket and sys_common::net::UdpSocket grow a new method called something like bind_reusable, which creates a reusable socket. The non-reusable bind should probably set SO_EXCLUSIVEADDRUSE on Windows; the reusable bind should set SO_REUSEADDR, and perhaps also SO_REUSEPORT on Linux. Alternatively, we could have the two bind methods on std::net::UdpSocket, but change the existing bind method on sys_common::net::UdpSocket to take a boolean flag or enum specifying reusability. I don't know to what extent you consider sys_common an implementation detail as opposed to an API. Thoughts? |
Another use-case: since |
I think UDP sockets should have the same behaviour as TCP and simply reuse port everytime. I agree it's a little weird TCP ignores TIME_WAIT, but anyway, this decision has already been made a long time ago, and it looks like noone had issue with it. |
Have there been any follow-ups on this topic? I'm using multicast UDP socket as well (in fact, published |
I think some people here might be confusing
(So it isn't actually this clear in practice since the flags come from different lineages. Under multicast they can be the same, @keepsimple1 What were you needing to use |
@jnordwick It may be worth noting that SO_REUSEADDR also allows processes to share ports. Indeed, it is the traditional and, i believe, only POSIX-compliant way to do this. SO_REUSEPORT is Linux-specific, and was added in 3.9, a mere nine years ago. FreeBSD has a SO_REUSEPORT, but i think it does something a bit different. I have no idea what MacOS has. But yes, anyone on Linux today almost certainly wants SO_REUSEPORT for the specific use cases discussed. Hence why i thought it was worthwhile creating a slightly higher-level API here, where you call a bind function appropriate to your use case, and it sets the right options for whatever platform you're on. Hey, on FreeBSD maybe that involves PCBGROUP, who knows. |
I didn't know it was so recent. I thought I remember using it before then, but might have been languishing in svn or I might not remember how recent that was. I think on FreeBSD you use SO_REUSEPORT_LB to get similar behavior to Linux. I have done some network programming but not a lot (or very recently) on FreeBSD. Here is an excellent rundown I found: To do a good BSD sockets layer with rust-like semantics and values, I agree you need to lift the API little. I dont know if higher is the right word, but definitely sideways. There are too many platform difference I think once you progress beyond the basics. Ever things as simple as sockopts behave differently or have to be called at different times (eg, before or after an Now, I write a lot of high performance, very low latency network code on Linux, and mostly on epoll, but lately also io_uring (set aside until it improves: io_uring + MSG_ZEROCOPY = pain) and PACKET_MMAP w/ eBPF (think io_uring without the rings). Maybe Rust shjould just go all out, support a workable BSD sockets and write new socket api that isnt' driven by BSD sockets and dosn't have to be tied to their cruft. open/close/send/recv isn't all there is out there. You shouldn't even need a read call. |
Actually I use both in my application as it runs on both Unix-like platforms and Windows. |
Issue by AngusL
Sunday Jul 20, 2014 at 17:56 GMT
For earlier discussion, see rust-lang/rust#15835
This issue was labelled with: A-libs in the Rust repository
I see there's been discussion of SO_REUSEADDR in the past. Mooted was that Windows allows later sockets to set the option and bind to endpoints which already have sockets without the option set, permitting a partial denial of service. (Later mitigated somewhat by SO_EXCLUSIVEADDRUSE.) TcpListener::bind currently uses this option to ignore the TIME_WAIT state, allowing faster re-binding. This introduces more-or-less the same problem in exchange for a benefit that's probably more useful in development than production.
There are other platform variations which make it difficult to find a unifying interface, particularly for TCP. In lieu of such an interface, I'd suggest exposing setsockopt(2) - even from an obviously platform-specific namespace. My motivation is a multicast discovery protocol, where I'd like multiple agents on one machine to be able to see each other. As far as I can tell, I need to either handle this separately or reinvent much of the UdpSocket wheel - which would be a shame.
The text was updated successfully, but these errors were encountered: