Conversation
On Windows, SO_REUSEADDR is not the TIME_WAIT-reuse knob that POSIX programmers expect: it enables 'stealing' binds, where a second socket can successfully bind to a port that another process is already bound to, with the two sockets then competing for incoming traffic. Two Server instances listening on the same port silently succeed instead of the second bind failing with WSAEADDRINUSE. SO_EXCLUSIVEADDRUSE is the documented Windows option for exclusive binding and restores the expected EADDRINUSE behavior. It only affects bind semantics, so client sockets (which connect without binding) are unaffected. References: yhirose#506, yhirose#1144, yhirose#2011; Microsoft docs for SO_EXCLUSIVEADDRUSE.
Owner
|
@dqsjqian Thank you for the PR and the detailed write-up. The current default is intentional. cpp-httplib enables address/port reuse on all platforms: If you need exclusive binding, you can replace the default options with svr.set_socket_options([](socket_t sock) {
#ifdef _WIN32
httplib::set_socket_opt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
#else
httplib::set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
#endif
});
Thanks for your consideration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Windows,
SO_REUSEADDRhas a very different meaning than on POSIX systems: it allows a socket to steal a bind — a second process can successfully bind to a port that another process is already bound to, and the two sockets then compete for incoming traffic. As a result, starting twoServerinstances on the same port silently succeeds on Windows, whereas on Linux/macOS the second bind fails withEADDRINUSEas expected.This was reported in #506, #1144 and #2011. As noted in #506, on Windows "using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE would be a correct answer" — but only the
SO_REUSEADDRhalf of that statement is currently implemented, and it alone produces the stealing behavior.Fix
In
default_socket_options, useSO_EXCLUSIVEADDRUSEon Windows instead ofSO_REUSEADDR.SO_EXCLUSIVEADDRUSEis the documented Windows option for exclusive binding: binding to an occupied port fails withWSAEADDRINUSE, matching POSIX expectations while still allowing a server to rebind its own port after restart (the primary use case ofSO_REUSEADDRthat #506 wants to keep —SO_EXCLUSIVEADDRUSEpermits rebinding a port in TIME_WAIT left over by a previous instance of the same server, it only blocks binding over another live socket).Non-Windows platforms are unchanged. Client sockets are unaffected:
SO_EXCLUSIVEADDRUSEonly affects bind semantics and cpp-httplib clients connect without binding.Notes
SO_EXCLUSIVEADDRUSEmust not later enableSO_REUSEADDR(setsockoptfails withWSAEINVAL). The only in-tree place that touchesSO_REUSEADDRon Windows after socket creation is the AF_UNIX workaround increate_socket, which sets it to 0 (disables it), which is compatible.