WCF 服务 - 客户端在对本地主机发出多次请求后收到 CommunicationException
WCF Service - Client receiving CommunicationException after many requests to localhost
我设置了一个基于 NetTcpBinding 的 WCF 服务,并且我正在使用本地主机。客户端和主机 运行 在同一台机器上。我在 while 循环中使用 WCF 服务接口的特定方法的客户端出现通信异常。 while 循环是强制性的,因为我正在监视一个值,而操作取决于值的变化。客户端是一个 clr 控制台应用程序,包含一个带有服务引用的 dll 和客户端的 app.config 文件。
为了尝试解决问题,我在绑定配置中增加了 openTimeout、closeTimeout、receiveTimeout、sendTimeout、maxBufferPoolSize 和 maxReceivedMessageSize,但没有成功。
我也让client的线程休眠,这样接口的方法就少调用了,但是也没有成功。
为了给你一个思路,你可以在下面找到调用接口方法的客户端的while循环。我也附上了客户端的绑定配置。
While 循环:
while (ClientOfIPCService.getUGUDasDouble(ControlUGUD) == ValueOfControlUGUD)
{
Console::WriteLine("Request acProgState...");
CurrentProgStat = ClientOfIPCService.getNCKVariableWithPathasDouble("/Channel/State/acProg[u1,1]");
if (CurrentProgStat == 0 || CurrentProgStat == 3 || CurrentProgStat == 4)
{
exit(0);
}
}
我现在的问题是如何解决这个问题?有没有可能我清空请求的缓冲区?如何避免此通信异常?
2019 年 1 月 8 日更新:
主机的完整 App.config 文件:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MexGet">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<!--Binding Settings-->
<bindings>
<netTcpBinding>
<binding name="BindingConfig1"
closeTimeout="00:30:00"
openTimeout="00:30:00"
receiveTimeout="00:30:00"
sendTimeout="00:30:00"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxStringContentLength="20000000"
maxArrayLength="20000000"
maxBytesPerRead="20000000"/>
</binding>
</netTcpBinding>
</bindings>
<!--Service Binding-->
<!--2. Configure end point with netTcpBinding-->
<services>
<service behaviorConfiguration="MexGet"
name="PROKOS_IPC_SERVER.HMI_IPC">
<endpoint name="NetTcpBindingEndpoint"
address=""
binding="netTcpBinding"
bindingConfiguration="BindingConfig1"
contract="PROKOS_IPC_SERVER.IHMI_IPC">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!--3. Configure the meta data exchange end point-->
<endpoint name="MexTcpBidingEndpoint"
address="mex"
binding="mexTcpBinding"
bindingConfiguration=""
contract="IMetadataExchange">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8124/HMI-IPC" />
</baseAddresses>
</host>
</service>
</services>
完整的 App.config 客户文件:
<system.serviceModel>
<!--Binding Settings-->
<bindings>
<netTcpBinding>
<binding name="BindingConfig1" closeTimeout="00:30:00" openTimeout="00:30:00"
receiveTimeout="00:30:00" sendTimeout="00:30:00" maxBufferPoolSize="20000000"
maxReceivedMessageSize="20000000" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8124/HMI-IPC" binding="netTcpBinding"
bindingConfiguration="BindingConfig1" contract="IPC.IHMI_IPC"
name="NetTcpBindingEndpoint">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
我在这里附上了服务器堆栈跟踪的屏幕截图:
Server stack trace
客户端完整报错信息为:
"The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.9549975'."
我没有在客户端处理异常,这在我的 clr 控制台应用程序中给出了以下错误消息。
Error message of client
2019 年 2 月 8 日更新:
以下代码展示了让线程休眠以避免多次请求的想法:
while (ClientOfIPCService.getUGUDasDouble(ControlUGUD) == ValueOfControlUGUD)
{
delay(500);
Console::WriteLine("Request acProgState...");
CurrentProgStat = ClientOfIPCService.getNCKVariableWithPathasDouble("/Channel/State/acProg[u1,1]");
if (CurrentProgStat == 0 || CurrentProgStat == 3 || CurrentProgStat == 4)
{
exit(0);
}
// lets the current thread sleep for X miliseconds
delay(500);
}
另一个想法是集成一种方法,我可以在 while 循环后剪断电线并再次打开它以供进一步使用。
2019 年 2 月 8 日更新:
我根据需要启用了 WCF 跟踪,我可以从跟踪中获取以下异常详细信息(请参阅消息的屏幕截图和下面的翻译):
"The socket was aborted because an asynchronous receive from the socket was not completed within the assigned time limit of 00:02:00. The time period allocated for this task may have been part of a longer timeout."
Service Trace of the WCF service
错误详情是什么?
由于Nettcpbinding默认使用消息安全模式和Windows账户作为客户端凭证,所以我们应该在客户端提供windows凭证,尽管服务器和客户端在同一台机器上。
此外,请 post 配置文件中完整的 System.servicemodel 部分。如需修改配置,请优先修改服务器的绑定配置。
如果问题仍然存在,请随时告诉我。
已更新。
我建议您将 Nettcpbinding 的安全模式明确指定为 NONE。
<bindings>
<netTcpBinding>
<binding name="willbeappliedontheendpoint">
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
同时删除不相关的配置。
那么我怀疑可能连接没有正常关闭,请尝试在退出前手动关闭循环内的通信连接。
另外,我们也可以尝试使用ChannelFactory来封装调用服务的函数。
https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.channelfactory-1?view=netframework-4.8
最后请参考下面的link,希望对你有用
The socket connection was aborted - CommunicationException
我设法解决了这个问题。以下是我的问题和解决方案的简短总结。
问题总结:
我创建了一个配置为 nettcpbinding 的 WCF 服务。我有一个包含 dll 的客户端,它构建为 clr 控制台应用程序(dll 包含客户端的 app.config 和使用添加服务引用创建的客户端代理)。客户端有一个带有 while 循环的函数,通过服务请求一个值。客户端的长时间 运行 我的服务抛出通信异常。
问题解决:
我使用 svcUtil.exe 创建了一个新代理,其中包含关闭和打开通道的方法。所以在我的函数中,我创建了一个新的客户端实例 class 并在函数的开头和结尾打开和关闭通道。此外,我让线程在 while 循环中休眠,以免向服务发出太多请求。
在 main 中的函数之后,我还为进一步的请求创建了一个新实例。这解决了我的问题。我客户端的函数代码如下:
while (myClient.getUGUDasDouble(ControlUGUD) == ValueOfControlUGUD)
{
delay(500);
//Console::WriteLine("Request acProgState...");
CurrentProgStat = myClient.getNCKVariableWithPathasDouble("/Channel/State/acProg[u1,1]");
if (CurrentProgStat == 0 || CurrentProgStat == 3 || CurrentProgStat == 4)
{
exit(0);
}
// lets the current thread sleep for X miliseconds
delay(500);
}
if (myClient.getUGUDasDouble(ControlUGUD) == 2)
{
myClient.setUGUDasDouble(ControlUGUD, -1);
}
else
{
MessageBox(0, (LPCWSTR)L"Error :::: IPC Communication Control: Function WaitTillNCFinishedTheJob() :::: Failure: NC needed to write MTU_G_C_NC = 2!", (LPCWSTR)L"Error", MB_ICONWARNING | MB_OK);
exit(0);
}
myClient.Close();
Console::WriteLine("Communication state: " + myClient.State.ToString());
因为我是 WCF 的新手,所以这种方法对我有用并且解决了我的问题。此问题的回调事件可能是更好的方法(参见 link)。
我设置了一个基于 NetTcpBinding 的 WCF 服务,并且我正在使用本地主机。客户端和主机 运行 在同一台机器上。我在 while 循环中使用 WCF 服务接口的特定方法的客户端出现通信异常。 while 循环是强制性的,因为我正在监视一个值,而操作取决于值的变化。客户端是一个 clr 控制台应用程序,包含一个带有服务引用的 dll 和客户端的 app.config 文件。
为了尝试解决问题,我在绑定配置中增加了 openTimeout、closeTimeout、receiveTimeout、sendTimeout、maxBufferPoolSize 和 maxReceivedMessageSize,但没有成功。
我也让client的线程休眠,这样接口的方法就少调用了,但是也没有成功。
为了给你一个思路,你可以在下面找到调用接口方法的客户端的while循环。我也附上了客户端的绑定配置。
While 循环:
while (ClientOfIPCService.getUGUDasDouble(ControlUGUD) == ValueOfControlUGUD)
{
Console::WriteLine("Request acProgState...");
CurrentProgStat = ClientOfIPCService.getNCKVariableWithPathasDouble("/Channel/State/acProg[u1,1]");
if (CurrentProgStat == 0 || CurrentProgStat == 3 || CurrentProgStat == 4)
{
exit(0);
}
}
我现在的问题是如何解决这个问题?有没有可能我清空请求的缓冲区?如何避免此通信异常?
2019 年 1 月 8 日更新:
主机的完整 App.config 文件:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MexGet">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<!--Binding Settings-->
<bindings>
<netTcpBinding>
<binding name="BindingConfig1"
closeTimeout="00:30:00"
openTimeout="00:30:00"
receiveTimeout="00:30:00"
sendTimeout="00:30:00"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxStringContentLength="20000000"
maxArrayLength="20000000"
maxBytesPerRead="20000000"/>
</binding>
</netTcpBinding>
</bindings>
<!--Service Binding-->
<!--2. Configure end point with netTcpBinding-->
<services>
<service behaviorConfiguration="MexGet"
name="PROKOS_IPC_SERVER.HMI_IPC">
<endpoint name="NetTcpBindingEndpoint"
address=""
binding="netTcpBinding"
bindingConfiguration="BindingConfig1"
contract="PROKOS_IPC_SERVER.IHMI_IPC">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!--3. Configure the meta data exchange end point-->
<endpoint name="MexTcpBidingEndpoint"
address="mex"
binding="mexTcpBinding"
bindingConfiguration=""
contract="IMetadataExchange">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8124/HMI-IPC" />
</baseAddresses>
</host>
</service>
</services>
完整的 App.config 客户文件:
<system.serviceModel>
<!--Binding Settings-->
<bindings>
<netTcpBinding>
<binding name="BindingConfig1" closeTimeout="00:30:00" openTimeout="00:30:00"
receiveTimeout="00:30:00" sendTimeout="00:30:00" maxBufferPoolSize="20000000"
maxReceivedMessageSize="20000000" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8124/HMI-IPC" binding="netTcpBinding"
bindingConfiguration="BindingConfig1" contract="IPC.IHMI_IPC"
name="NetTcpBindingEndpoint">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
我在这里附上了服务器堆栈跟踪的屏幕截图:
Server stack trace
客户端完整报错信息为: "The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.9549975'."
我没有在客户端处理异常,这在我的 clr 控制台应用程序中给出了以下错误消息。
Error message of client
2019 年 2 月 8 日更新:
以下代码展示了让线程休眠以避免多次请求的想法:
while (ClientOfIPCService.getUGUDasDouble(ControlUGUD) == ValueOfControlUGUD)
{
delay(500);
Console::WriteLine("Request acProgState...");
CurrentProgStat = ClientOfIPCService.getNCKVariableWithPathasDouble("/Channel/State/acProg[u1,1]");
if (CurrentProgStat == 0 || CurrentProgStat == 3 || CurrentProgStat == 4)
{
exit(0);
}
// lets the current thread sleep for X miliseconds
delay(500);
}
另一个想法是集成一种方法,我可以在 while 循环后剪断电线并再次打开它以供进一步使用。
2019 年 2 月 8 日更新:
我根据需要启用了 WCF 跟踪,我可以从跟踪中获取以下异常详细信息(请参阅消息的屏幕截图和下面的翻译):
"The socket was aborted because an asynchronous receive from the socket was not completed within the assigned time limit of 00:02:00. The time period allocated for this task may have been part of a longer timeout."
Service Trace of the WCF service
错误详情是什么?
由于Nettcpbinding默认使用消息安全模式和Windows账户作为客户端凭证,所以我们应该在客户端提供windows凭证,尽管服务器和客户端在同一台机器上。
此外,请 post 配置文件中完整的 System.servicemodel 部分。如需修改配置,请优先修改服务器的绑定配置。
如果问题仍然存在,请随时告诉我。
已更新。
我建议您将 Nettcpbinding 的安全模式明确指定为 NONE。
<bindings>
<netTcpBinding>
<binding name="willbeappliedontheendpoint">
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
同时删除不相关的配置。
那么我怀疑可能连接没有正常关闭,请尝试在退出前手动关闭循环内的通信连接。
另外,我们也可以尝试使用ChannelFactory来封装调用服务的函数。
https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.channelfactory-1?view=netframework-4.8
最后请参考下面的link,希望对你有用
The socket connection was aborted - CommunicationException
我设法解决了这个问题。以下是我的问题和解决方案的简短总结。
问题总结: 我创建了一个配置为 nettcpbinding 的 WCF 服务。我有一个包含 dll 的客户端,它构建为 clr 控制台应用程序(dll 包含客户端的 app.config 和使用添加服务引用创建的客户端代理)。客户端有一个带有 while 循环的函数,通过服务请求一个值。客户端的长时间 运行 我的服务抛出通信异常。
问题解决: 我使用 svcUtil.exe 创建了一个新代理,其中包含关闭和打开通道的方法。所以在我的函数中,我创建了一个新的客户端实例 class 并在函数的开头和结尾打开和关闭通道。此外,我让线程在 while 循环中休眠,以免向服务发出太多请求。
在 main 中的函数之后,我还为进一步的请求创建了一个新实例。这解决了我的问题。我客户端的函数代码如下:
while (myClient.getUGUDasDouble(ControlUGUD) == ValueOfControlUGUD)
{
delay(500);
//Console::WriteLine("Request acProgState...");
CurrentProgStat = myClient.getNCKVariableWithPathasDouble("/Channel/State/acProg[u1,1]");
if (CurrentProgStat == 0 || CurrentProgStat == 3 || CurrentProgStat == 4)
{
exit(0);
}
// lets the current thread sleep for X miliseconds
delay(500);
}
if (myClient.getUGUDasDouble(ControlUGUD) == 2)
{
myClient.setUGUDasDouble(ControlUGUD, -1);
}
else
{
MessageBox(0, (LPCWSTR)L"Error :::: IPC Communication Control: Function WaitTillNCFinishedTheJob() :::: Failure: NC needed to write MTU_G_C_NC = 2!", (LPCWSTR)L"Error", MB_ICONWARNING | MB_OK);
exit(0);
}
myClient.Close();
Console::WriteLine("Communication state: " + myClient.State.ToString());
因为我是 WCF 的新手,所以这种方法对我有用并且解决了我的问题。此问题的回调事件可能是更好的方法(参见 link)。