本地HTTP请求发送时出现Socket Error 10013的原因及解决方法
SocketException(10013) 间歇性出现的原因与解决方法
环境架构
- 对外暴露的IIS ARR代理(端口443)
- Service A:.NET 6 Windows服务,Kestrel监听
localhost:6101 - 本地IIS ARR代理(仅接受本地流量,端口6200)
- Service B:.NET 6 Windows服务,Kestrel监听
localhost:6201
问题现象
随机出现502.3错误,频率从每小时1次到几天1次,平均每日1次。异常时Service A向localhost:6200/some_endpoint发起请求失败,抛出以下异常:
2024-08-29 06:09:59,694 [116] ERROR System.Net.Http.HttpRequestException: An attempt was made to access a socket in a way forbidden by its access permissions. (127.0.0.1:6200) ---> System.Net.Sockets.SocketException (10013): An attempt was made to access a socket in a way forbidden by its access permissions. at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken) at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token) at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|277_0(AwaitableSocketAsyncEventArgs saea, ValueTask connectTask, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request) at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at Microsoft.Extensions.Http.PolicyHttpMessageHandler.SendCoreAsync(HttpRequestMessage request, Context context, CancellationToken cancellationToken) at Polly.Timeout.AsyncTimeoutEngine.ImplementationAsync[TResult](Func`3 action, Context context, CancellationToken cancellationToken, Func`2 timeoutProvider, TimeoutStrategy timeoutStrategy, Func`5 onTimeoutAsync, Boolean continueOnCapturedContext) at Polly.Timeout.AsyncTimeoutEngine.ImplementationAsync[TResult](Func`3 action, Context context, CancellationToken cancellationToken, Func`2 timeoutProvider, TimeoutStrategy timeoutStrategy, Func`5 onTimeoutAsync, Boolean continueOnCapturedContext) at Polly.AsyncPolicy`1.ExecuteAsync(Func`3 action, Context context, CancellationToken cancellationToken, Boolean continueOnCapturedContext) at Microsoft.Extensions.Http.PolicyHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) ...
- 异常会在3-10分钟后自动恢复
- Service B运行正常,无报错
潜在原因分析
Windows端口限制耗尽
Windows默认单个进程可用的出站端口范围是1024-65535,约64k端口。如果Service A短时间发起大量请求到6200端口,会快速耗尽可用本地出站端口,新请求无法创建Socket连接,触发10013错误。端口释放需等待TIME_WAIT状态结束(默认240秒),这也对应了3-10分钟自动恢复的现象。IIS ARR代理连接限制
本地6200端口的IIS ARR代理可能设置了连接数上限,当并发请求达到阈值时,代理会拒绝新连接,Windows会将这类拒绝映射为10013权限错误。Service A的HttpClient配置不合理
如果Service A未复用HttpClient实例(每次请求新建),或连接池参数配置过低,会导致频繁创建新连接,加速端口耗尽或触发代理连接限制。本地安全策略/防火墙临时拦截
虽然是本地请求,Windows防火墙动态规则或本地安全策略可能临时阻止Service A的出站连接,这类拦截通常短暂,会自动恢复。
解决方法
1. 调整Windows端口与TIME_WAIT设置
- 扩大可用端口范围(管理员CMD执行):
netsh int ipv4 set dynamicport tcp start=1024 num=64511 netsh int ipv4 set dynamicport udp start=1024 num=64511 - 缩短TIME_WAIT超时时间(修改注册表,需重启服务器生效):
reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v TcpTimedWaitDelay /t REG_DWORD /d 30 /f
2. 优化IIS ARR代理配置
- 打开IIS管理器,找到6200端口站点,进入高级设置:
- 调高最大并发连接数(根据实际流量设为1000或更高)
- 进入ARR缓存配置,调整连接池大小与超时时间,避免代理过早拒绝连接
3. 优化Service A的HttpClient配置
- 复用HttpClient实例:使用
IHttpClientFactory管理生命周期,避免每次请求新建HttpClient。 - 调整连接池参数(Program.cs中配置):
builder.Services.AddHttpClient("ServiceBProxy") .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { MaxConnectionsPerServer = 100, // 根据并发量调整 AllowAutoRedirect = false, UseCookies = false }); - 添加Polly重试策略:针对SocketException(10013)重试,避免单次失败导致502:
builder.Services.AddHttpClient("ServiceBProxy") .AddPolicyHandler(Policy.Handle<SocketException>(ex => ex.SocketErrorCode == SocketError.AccessDenied) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
4. 检查本地安全策略与防火墙
- 打开
secpol.msc,进入安全设置 > 本地策略 > 用户权限分配:确保Service A运行账户拥有从网络访问此计算机权限。 - 检查Windows防火墙,添加永久允许规则:允许Service A向127.0.0.1:6200发起出站连接。
内容的提问来源于stack exchange,提问作者andy250
相关产品推荐
相关产品推荐

