You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6部署Windows Server无法连接WCF服务问题排查

WCF客户端在.NET 6/.NET Core部署到Windows Server 2019失败问题排查

问题概述

通过「添加WCF服务引用」创建的客户端,配置自定义SSL客户端证书后,本地运行的.NET 6/.NET Core 3.1版本可正常工作,但部署到Windows Server 2019服务器后出现连接中止错误(SocketException 10053),仅.NET Framework 4.7.2版本能正常运行。

客户端核心代码

using ConsoleAppFramework.MyServiceReference;
using System;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel.Security;
using System.Threading.Tasks;

namespace ConsoleAppFramework
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            SoapServicesClient client = new SoapServicesClient();

            client.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(@"C:\My-Client-Cert.p12", "pass");

            client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
            {
                CertificateValidationMode = X509CertificateValidationMode.None,
                RevocationMode = X509RevocationMode.NoCheck
            };

            client.Open();

            var res = await client.loginStaticAsync(Array.Empty<contextEntry>(), new userInfoRequestBean()
            {
                username = "user",
                password = "pass"
            });

            client.Close();

            Console.WriteLine(res.@return.sessionId);
        }
    }
}

错误堆栈

Unhandled exception. System.ServiceModel.CommunicationException: An error occurred while sending the request.
 ---&gt; System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---&gt; System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine..
 ---&gt; System.Net.Sockets.SocketException (10053): An established connection was aborted by the software in your host machine.
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.&lt;FillBufferAsync&gt;g__InternalFillBufferAsync|215_0[TReadAdapter](TReadAdapter adap, ValueTask`1 task, Int32 min, Int32 initial)
   at System.Net.Security.SslStream.ReadAsyncInternal[TReadAdapter](TReadAdapter adapter, Memory`1 buffer)
   at System.Net.Http.HttpConnection.FillAsync()
   at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.AuthenticationHelper.SendWithNtAuthAsync(HttpRequestMessage request, Uri authUri, ICredentials credentials, Boolean isProxyAuth, HttpConnection connection, HttpConnectionPool connectionPool, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.AuthenticationHelper.SendWithAuthAsync(HttpRequestMessage request, Uri authUri, ICredentials credentials, Boolean preAuthenticate, Boolean isProxyAuth, Boolean doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.SendRequestAsync(Message message, TimeoutHelper timeoutHelper)
   --- End of inner exception stack trace ---
   at ConsoleAppCore3_1.Program.Main(String[] args) in C:\Users\......\Program.cs:line 45
   at ConsoleAppCore3_1.Program.&lt;Main&gt;(String[] args)

.NET Framework 4.7.2与.NET 6 WCF客户端的核心差异

  • HTTP底层实现:.NET Framework依赖System.Net.HttpWebRequest,.NET Core/.NET 6改用System.Net.Http.HttpClient,SSL/TLS握手逻辑、配置方式存在明显差异。
  • 证书加载规则:.NET Framework对证书文件权限要求宽松,且兼容旧版证书存储逻辑;.NET Core/.NET 6加载PKCS#12(.p12)证书时默认不导出私钥,且对文件/存储读取权限校验更严格。
  • SSL/TLS协议支持:.NET Framework默认继承系统SSL配置,.NET Core/.NET 6默认仅启用TLS 1.2/1.3,若WCF服务仅支持旧协议(如TLS 1.0/1.1)会直接握手失败。
  • 代理处理逻辑:.NET Framework自动继承系统代理设置,.NET Core/.NET 6需显式配置代理参数。

针对Windows Server 2019部署问题的解决方案

1. 调整证书加载方式

方式一:导入证书到Windows存储

将.p12证书导入Windows Server 2019的「本地计算机-个人」存储,通过证书指纹加载,避免文件权限问题:

var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, "你的证书指纹", false);
if (certs.Count > 0)
{
    client.ClientCredentials.ClientCertificate.Certificate = certs[0];
}
store.Close();

注意:需确保运行客户端的账户(如应用池账户、本地系统账户)有读取证书存储的权限。

方式二:修改证书加载参数

加载.p12时显式指定私钥可导出、使用机器密钥集,适配服务器部署场景:

client.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(
    @"C:\My-Client-Cert.p12", 
    "pass", 
    X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet
);

2. 显式配置SSL/TLS协议

若WCF服务不支持TLS 1.2/1.3,强制指定兼容协议:

// 在创建WCF客户端前添加
System.Net.ServicePointManager.SecurityProtocol = 
    System.Net.SecurityProtocolType.Tls12 | 
    System.Net.SecurityProtocolType.Tls11 | 
    System.Net.SecurityProtocolType.Tls;

3. 检查服务器环境配置

  • 确认Windows Server 2019防火墙允许客户端访问WCF服务端口(通常为443);
  • 若服务器使用代理,需在客户端显式配置代理:
var httpClientHandler = new HttpClientHandler
{
    Proxy = new WebProxy("http://代理地址:端口"),
    UseProxy = true
};
// 将handler关联到WCF绑定(需自定义绑定配置)

4. 启用WCF跟踪日志排查

添加配置生成详细日志,定位握手失败具体原因:

<!-- 写入app.config或appsettings.json对应配置节点 -->
<system.diagnostics>
    <sources>
        <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
            <listeners>
                <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\logs\WcfTrace.svclog" />
            </listeners>
        </source>
    </sources>
</system.diagnostics>

内容的提问来源于stack exchange,提问作者dev-masih

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:35:21