我正在构建Windows服务应用程序,它必须定期调用WCF服务。问题是服务的第一次调用总是成功的,我得到了预期的响应,但第二次和任何其他请求失败后我得到以下异常:
System.ServiceModel.CommunicationException:接收到https:XXXXXXXXXXXX的HTTP响应时发生错误。这可能是由于服务端点绑定不使用HTTP协议。这也可能是由于服务器中止HTTP请求上下文(可能是由于服务关闭)。请参阅服务器日志以获取更多详---> System.Net.WebException:基础连接已关闭:接收时发生意外错误。 ---> System.IO.IOException:无法从传输连接读取数据:远程主机强制关闭现有连接。 ---> System.Net.Sockets.SocketException:远程主机强制关闭现有连接 在System.Net.Sockets.Socket.Receive(Byte []缓冲区,Int32偏移量,Int32大小,SocketFlags socketFlags) ...
我的Windows服务是使用System.ServiceProcess.ServiceBase构建的。 对于定期调用,我使用System.Timers.Timer类,如下所示:
protected override void OnStart(string[] args)
{
try
{
InitTimer();
}
catch (Exception ex)
{
ExceptionHandler.HandleException(ex);
}
}
private void InitTimer()
{
Timer apiPollingTimer = new Timer(60000); // 1 minute
apiPollingTimer.Elapsed += ((sender, e) =>
{
OnTimerElapsed(sender, e);
});
apiPollingTimer.Enabled = true;
apiPollingTimer.AutoReset = true;
apiPollingTimer.Start();
}
protected void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
ServiceClient client = new ServiceClient();
ServiceResult result = client.GetUpdateTimes();
client.Close();
}
catch (Exception ex)
{
ExceptionHandler.HandleException(ex);
}
}
这是WCF端点的绑定配置:
<basicHttpBinding>
<binding name="transportSecurity" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="655360000" maxBufferPoolSize="524288" maxReceivedMessageSize="655360000"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="655360000"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
编辑:这是客户端和行为配置:
<client>
<endpoint address="https://XXXXXXXXXXXX"
behaviorConfiguration="ClientCertBehavior"
binding="basicHttpBinding" bindingConfiguration="transportSecurity"
contract="GetUpdateTimesInterface"
name="GetUpdateTimes" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertBehavior">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySerialNumber" findValue="xx xx xx"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
编辑2:绑定服务wsdl的部分:
<wsdl:binding name="ServiceSoapBinding" type="tns:GetUpdateTimesInterface">
<soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetUpdateTimes">
<soap12:operation soapAction="urn:GetUpdateTimes" style="document"/>
<wsdl:input name="GetUpdateTimes">
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output name="GetUpdateTimesResponse">
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="GetUpdateTimesService">
<wsdl:port name="GetUpdateTimes" binding="tns:ServiceSoapBinding">
<soap12:address location="http:XXXXX"/>
</wsdl:port>
</wsdl:service>
我到目前为止尝试的是更改配额属性,但它没有帮助,我仍然得到相同的异常第二次调用服务。此外,如果我制作简单的控制台应用程序,我复制粘贴相同的计时器实现和绑定配置我没有得到异常,服务被调用并每次返回响应,它只在我安装此Windows服务时失败。
此外,我无法访问WCF服务实现,只能使用wsdl。
非常感谢任何帮助。
编辑3: 我已经使用Fiddler进行了一些检查,我注意到的是第一次将服务称为头连接:添加Keep-Alive并且SessionID为空,而第二次添加SessionID。我想也许有一种方法可以删除Connection:Keep-Alive来自调用或清除SessionID(如果它存在会有帮助)。以下是来自Fiddler的图片请求/回复:Image
编辑4:
尝试用customBinding替换basicHttpBinding并设置keepAliveEnabled但它没有帮助:
<customBinding>
<binding name="customTransportSecurity" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
<textMessageEncoding messageVersion="Soap12" writeEncoding="utf-8" />
<httpsTransport keepAliveEnabled="false" transferMode="Buffered" requireClientCertificate="true"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="655360000" maxBufferPoolSize="524288" maxReceivedMessageSize="655360000" realm="" />
</binding>
</customBinding>