WCF服务停止工作10054 WSAECONNRESET对等方重置连接

本文关键字:对等 方重置 连接 WSAECONNRESET 10054 服务 停止工作 WCF | 更新日期: 2023-09-27 18:22:40

我有两个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的Faultd()、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);
}

自定义端点行为

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)
    {
    }
}

自定义服务行为

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)
    {
    }
}

谢谢!

WCF服务停止工作10054 WSAECONNRESET对等方重置连接

我回到这个问题,终于找到了解决方案。

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

问题:

  1. 您有证书(不是自签名证书)
  2. 您可以使用命令"netsh http add sslcert"将此证书与windows端口关联,并在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(-2146898813 NTE_BAD_KEY_STATE)CertUtil:密钥在指定状态下无效。

如何重现所有配置过程:

  1. 从.pfx获取证书:

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

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

    X509Store store=新的X509Store(storeName.My,StoreLocation.LocalMachine);百货商店打开(OpenFlags.ReadWrite);百货商店添加(证书);百货商店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在开发人员之后停止工作的问题重新启动他们的机器。(不知道它是怎么发生的,但它确实发生了始终如一。)我终于通过出口和再进口解决了这个问题将自签名证书放入受信任的根目录(而不是简单地拖动它)。现在我的自签名证书被考虑,我不需要每次重新启动机器

神奇的是,您不需要从个人证书存储导出证书,也不需要在根目录中导入证书。您只需要在重新启动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