diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs index 6f4e2ed63e77b..736015bb01435 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Windows.cs @@ -235,9 +235,34 @@ partial void WildcardBindForConnectIfNecessary(AddressFamily addressFamily) if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, csep.IPEndPoint); + if (_socketType == SocketType.Stream && _protocolType == ProtocolType.Tcp) + { + EnableReuseUnicastPort(); + } + DoBind(csep.IPEndPoint, csep.SocketAddress); } + private void EnableReuseUnicastPort() + { + // By enabling SO_REUSE_UNICASTPORT, we defer actual port allocation until the ConnectEx call, + // so it can bind to ports from the Windows auto-reuse port range, if configured by an admin. + // The socket option is supported on Windows 10+, we are ignoring the SocketError in case setsockopt fails. + int optionValue = 1; + SocketError error = Interop.Winsock.setsockopt( + _handle, + SocketOptionLevel.Socket, + SocketOptionName.ReuseUnicastPort, + ref optionValue, + sizeof(int)); + + if (NetEventSource.Log.IsEnabled() && error != SocketError.Success) + { + error = SocketPal.GetLastSocketError(); + NetEventSource.Info($"Enabling SO_REUSE_UNICASTPORT failed with error code: {error}"); + } + } + internal unsafe bool ConnectEx(SafeSocketHandle socketHandle, IntPtr socketAddress, int socketAddressSize,