【问题标题】:WCF service stop working 10054 WSAECONNRESET Connection reset by peerWCF 服务停止工作 10054 WSAECONNRESET 连接被对等方重置
【发布时间】:2015-11-18 15:30:02
【问题描述】:

我有两个 WCF 服务在我的计算机 (Windows 8) 的 Windows 窗体应用程序 (C# / .NET 4) 中运行:

第一次服务:https://localhost:9002

二次服务:https://local_192-168-1-104.desktop.Company.com:9003

第一个服务是本地访问的,第二个服务是本地网络中的其他计算机访问的。主机:local_192-168-1-104.desktop.Company.com被DNS解析为ip:192.168.1.104,这是我的本地网络ip地址。

两个服务都使用 https,第一个使用 SelfSigned 证书,第二个使用证书:desktop.Company.com

问题:在一段时间不活动后,第二个服务停止工作。

没有异常被记录并且WebServiceHost的事件Faulted()、UnknownMessageReceived()、Closing()或者Closed()没有被执行。

如果我关闭应用程序并重新启动它,问题仍然存在。在这种错误情况下,WebServiceHost 的 State 属性为“Opened”,但服务没有响应。

如果我停止服务,重新配置服务(主题:配置证书服务 2),然后再次启动,问题会停止一段时间。

我使用这个测试 wcf 服务:

using (WebClient webClient = new WebClient())
{
    webClient.DownloadDataCompleted += webClient_DownloadDataCompleted;
    webClient.DownloadDataAsync(new Uri("https://local_192-168-1-104.desktop.Company.com:9003/Message/Test"));
}

我收到了这个例外:

底层连接已关闭:发送时发生意外错误。

>> INNER EXCEPTION:
Message: An existing connection was forcibly closed by the remote host
Type: System.Net.Sockets.SocketException (System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
Source: System
TargetSite: Int32 EndReceive(System.IAsyncResult)
ErrorCode: 10054
StackTrace:
---------------------------
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
---------------------------

Windows 错误代码 10054 是:

对等方重置连接。

现有连接被远程主机强行关闭。这个 通常如果远程主机上的对等应用程序是 突然停止,主机重启,主机或远程网络 接口被禁用,或远程主机使用硬关闭(请参阅 setsockopt 以获取有关远程 SO_LINGER 选项的更多信息 插座)。如果连接因以下原因而中断,也可能导致此错误 在一个或多个操作时检测故障的保持活动 正在进行中。正在进行的操作失败 WSAENETRESET。后续操作因 WSAECONNRESET 而失败。

我尝试禁用 Keep Alive,但问题仍然存在。

更多详情如下:

配置证书服务1

netsh http delete urlacl url=https://+:9002/
netsh http delete sslcert ipport=0.0.0.0:9002
netsh http add urlacl url=https://+:9002/ user=Everyone
makecert -sk RootCA -sky signature -pe -n CN=localhost -r -sr LocalMachine -ss Root certificate\CustomCertificate_MyCA.cer
makecert -sk server -sky exchange -pe -n CN=localhost -ir LocalMachine -is Root -ic certificate\CustomCertificate_MyCA.cer -sr LocalMachine -ss My certificate\CustomCertificate.cer
(install certificate in CertificateStore)
netsh http add sslcert ipport=0.0.0.0:9002 certhash=F3F40BF81AF0.... appid={00a1d32c-68bd-4693-a872-...}

启动服务1

var mainServiceHost = new Company.Library.WCF.JSONServiceHost("localhost", 9002, true);
mainServiceHost.Start(typeof(Service.Message), typeof(Service.IMessage), false);

配置证书服务2

netsh http delete urlacl url=https://+:9002/
netsh http delete sslcert ipport=192.168.1.146:9003
netsh http add urlacl url=https://+:9003/ user=Everyone
(install certificate in CertificateStore)
netsh http add sslcert ipport=192.168.1.146:9003 certhash=1C36C9C... appid={00a1d32c-68bd-4693-a872-1473...}

启动服务2

var localServerServiceHost = new Company.Library.WCF.JSONServiceHost("local_192-168-1-104.desktop.Company.com", 9003, true);
localServerServiceHost.Start(typeof(Service.Message), typeof(Service.IMessage), false);

JSONServiceHost 类

public void Start(Type serviceType, Type implementedContract, bool keepAliveEnabled)
{
    EndpointAddress endpoint = new EndpointAddress(Url);

    CustomServiceBehavior serviceBehavior = new CustomServiceBehavior();
    svcWebHost.Description.Behaviors.Add(serviceBehavior);

    BindingElementCollection bindingElements;

    WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport);

    bindingElements = binding.CreateBindingElements();
    if (bindingElements != null)
    {
        var transport = bindingElements.Find<HttpsTransportBindingElement>();
        if (transport != null)
            transport.KeepAliveEnabled = keepAliveEnabled;
    }

    binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
    binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
    binding.ReaderQuotas.MaxDepth = int.MaxValue;
    binding.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
    binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
    binding.MaxBufferSize = int.MaxValue;
    binding.MaxBufferPoolSize = int.MaxValue;
    binding.MaxReceivedMessageSize = int.MaxValue;

    binding.SendTimeout = TimeSpan.FromMinutes(5);
    binding.ReceiveTimeout = TimeSpan.FromMinutes(5);
    binding.OpenTimeout = TimeSpan.FromMinutes(5);
    binding.CloseTimeout = TimeSpan.FromMinutes(5);

    ServiceEndpoint serviceEndpoint = svcWebHost.AddServiceEndpoint(implementedContract, binding, endpoint.Uri);

    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    svcWebHost.Description.Behaviors.Add(smb);

    ServiceDebugBehavior sdb = svcWebHost.Description.Behaviors.Find<ServiceDebugBehavior>();
    if (sdb != null)
        sdb.IncludeExceptionDetailInFaults = true;

    foreach (var operation in serviceEndpoint.Contract.Operations)
        operation.Behaviors.Add(new CustomOperationBehavior());

    svcWebHost.Open();
}

应用程序启动时执行的附加配置

private static void ConfigureGlobalServiceParameters()
{
    System.Net.ServicePointManager.CheckCertificateRevocationList = false;
    System.Net.ServicePointManager.DefaultConnectionLimit = int.MaxValue;
    System.Net.ServicePointManager.DnsRefreshTimeout = -1;
    System.Net.ServicePointManager.Expect100Continue = false;
    System.Net.ServicePointManager.MaxServicePointIdleTime = 20 * 1000;
    System.Net.ServicePointManager.MaxServicePoints = 10;
    System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(delegate { return true; });
    System.Net.ServicePointManager.UseNagleAlgorithm = false;
    System.Net.ServicePointManager.SetTcpKeepAlive(false, 0, 0);
}

CustomEndpointBehavior

public class CustomEndpointBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        var customInspector = new CustomDispatchMessageInspector();
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(customInspector);
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

自定义操作行为

public class CustomOperationBehavior : IOperationBehavior
{
    public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
    {   
    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
    {
    }

    public void Validate(OperationDescription operationDescription)
    {
    }
}

CustomServiceBehavior

public class CustomServiceBehavior : IServiceBehavior
{
    public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        CustomEndpointBehavior endpointBehavior = new CustomEndpointBehavior();
        foreach (var endpoint in serviceDescription.Endpoints)
            endpoint.Behaviors.Add(endpointBehavior);
    }

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }
}

谢谢!

【问题讨论】:

  • 附加信息:我创建了一个线程每 5 分钟测试一次服务,使用这个问题永远不会发生。

标签: c# wcf


【解决方案1】:

回到这个问题,终于找到了解决办法。

这不是 WCF 的问题,WCF 停止工作是因为证书与 windows 端口的关联不起作用。

问题:

  1. 您有证书(不是自签名证书);
  2. 您可以使用以下命令将此证书与 Windows 端口相关联:“netsh http add sslcert”并在 WCF 或其他服务中使用它;
  3. 重启后,或系统长时间闲置,停止工作;

后果:

windows 重启后,服务停止在此端口工作,并出现以下描述的行为:

  1. 如果您尝试对 url 执行 Http 请求,您会收到以下错误: 底层连接已关闭:发送时发生意外错误。

  2. 如果您尝试再次将证书关联到端口,请使用以下命令:

命令:netsh http add sslcert ipport=192.168.1.146:9003 certhash=1C36.. appid={00a1..}

您收到此错误:

SSL 证书添加失败,错误:1312 指定的登录会话不存在。它可能已经被终止了。

  1. 如果您尝试导出证书,请使用以下命令:

命令:certutil -exportPFX -p "[password]" My [cert_SerialNumber] "c:\temp\desktop.pfx" NoChain

您收到此错误:

私钥不可导出 加密测试通过 CertUtil:-exportPFX 命令失败:0x8009000b (-2146893813 NTE_BAD_KEY_STATE) CertUtil:密钥在指定状态下无效。

如何重现所有配置过程:

  1. 从 .pfx 获取证书:

代码:X509Certificate2 certificate = new X509Certificate2(certPath, password);

  1. 将证书证书添加到CertificateStore(StoreName:“MY”,StoreLocation:LocalMachine):

    X509Store store = new X509Store(storeName.My, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadWrite); store.Add(证书); store.Close();

  2. 将证书附加到端口:

命令:netsh http add sslcert ipport=192.168.1.146:9003 certhash=1C36C... appid={00a..} clientcertnegotiation=enable

  1. 配置 windows 防火墙以允许访问端口:

(我这样做是因为我正在从本地网络中的另一台计算机访问 WCF)

如何手动解决问题:

在这篇文章中: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx

有这个解决办法:

我认为通过将自签名证书从个人移动到受信任的根 CA目录导致开发者后SSL停止工作的问题 重新启动他们的机器。 (不知道它是怎么发生的,但它确实发生了 始终如一。)我终于通过导出和重新导入解决了这个问题 将自签名证书放入受信任的根目录(而不是 只需将其拖过来)。现在考虑我的自签名证书,我 每次重新启动时都不需要重新安装/修复 IIS Express 机器。

神奇的是,您不需要从个人证书存储中导出证书,并在根目录中导入证书。只需要在windows重启前手动导出证书,windows重启后就不会出现问题了。

如何使用命令行解决问题:

在配置过程之后,在第一个窗口重新启动之前,执行这个:

  1. 将证书导入“个人”证书存储:

命令:certutil -f -p "[password]" -importpfx My "c:\temp\cert.pfx"

  1. 使用此导出证书:

命令:certutil -exportPFX -p "[password]" My [certificate_Serial_Number] "c:\temp\cert2.pfx" NoChain

有价值的信息:

  1. 列出安装在 Windows 本地计算机证书存储中的证书:

    • 开始/运行:mmc.exe
    • 文件/添加/删除管理单元...
    • 在可用的管理单元下,选择“证书”,然后选择“本地计算机”并按添加。
  2. 使用命令“netsh http add sslcert”列出与端口关联的证书

命令:certutil -store "My"

  1. 要删除证书与端口的关联:

命令:netsh http delete sslcert ipport=192.168.1.104:9003

  1. certutil 参考:

https://technet.microsoft.com/en-us/library/cc732443.aspx

  1. netsh 参考:

https://msdn.microsoft.com/en-us/library/windows/desktop/cc307220(v=vs.85).aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多