From 90a3a48ac50aab18013d3db2eb62c7cd7beef2f6 Mon Sep 17 00:00:00 2001 From: dqsjqian Date: Mon, 14 Sep 2026 18:03:25 +0800 Subject: [PATCH] Use SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR on Windows 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: #506, #1144, #2011; Microsoft docs for SO_EXCLUSIVEADDRUSE. --- httplib.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/httplib.h b/httplib.h index bf22373ffa..faddec7000 100644 --- a/httplib.h +++ b/httplib.h @@ -10902,6 +10902,16 @@ inline bool setup_client_tls_session( */ inline void default_socket_options(socket_t sock) { +#ifdef _WIN32 + // On Windows, SO_REUSEADDR has a different, dangerous meaning: it allows a + // socket to bind to a port that another socket is already bound to (i.e. + // the bind silently steals the port) instead of returning WSAEADDRINUSE. + // Use SO_EXCLUSIVEADDRUSE to get the POSIX-like exclusive binding; a bind + // to an occupied port then fails with WSAEADDRINUSE. (SO_EXCLUSIVEADDRUSE + // only affects bind, so this is harmless for client sockets which connect + // without binding.) + set_socket_opt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1); +#else set_socket_opt(sock, SOL_SOCKET, #ifdef SO_REUSEPORT SO_REUSEPORT, @@ -10909,6 +10919,7 @@ inline void default_socket_options(socket_t sock) { SO_REUSEADDR, #endif 1); +#endif } inline bool set_socket_opt(socket_t sock, int level, int optname, int optval) {