繁体   English   中英

WCF服务-对本地主机的许多请求后,客户端收到CommunicationException

[英]WCF Service - Client receiving CommunicationException after many requests to localhost

我设置了一个基于NetTcpBinding的WCF服务,并且正在使用localhost。 客户端和主机在同一台计算机上运行。 在while循环中,使用WCF服务接口的特定方法的客户端收到通信异常。 while循环是强制性的,因为我正在监视一个值,并且操作取决于值的更改。 客户端是一个clr控制台应用程序,包含一个带有服务参考的dll和该客户端的app.config文件。

为了尝试解决该问题,我在绑定配置中增加了openTimeout,closeTimeout,receiveTimeout,sendTimeout,maxBufferPoolSize和maxReceivedMessageSize,但没有成功。

我还让客户端线程处于休眠状态,这样接口的方法被较少调用,但是也没有成功。

为了给您一个想法,您可以在下面找到调用接口方法的客户端的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);
            }
        }

我现在的问题是如何解决这个问题? 我是否有可能清空请求的缓冲区? 如何避免这种通信异常?

更新01/08/2019:

主机的完整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>

在这里,我附上了服务器堆栈跟踪的屏幕截图:

服务器堆栈跟踪

客户端的完整错误消息是:“套接字连接已中止。这可能是由于处理您的消息时发生错误或远程主机超出了接收超时,或者是潜在的网络资源问题。本地套接字超时为'00 :29:59.9549975'。”

我没有在客户端处理异常,这在我的clr控制台应用程序中给我以下错误消息。

客户端错误信息

更新02/08/2019:

以下代码显示了让线程休眠以避免许多请求的想法:

        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循环后切断导线,然后再次打开以进一步使用。

更新02/08/2019:

我根据需要启用了WCF跟踪,并且可以从跟踪中获取以下异常详细信息(请参阅消息的屏幕截图和下面的翻译):

“套接字被中止,因为从套接字的异步接收未在分配的时间限制00:02:00内完成。为此任务分配的时间段可能是更长超时的一部分。”

WCF服务的服务跟踪

错误的详细信息是什么?
由于默认情况下Nettcpbinding使用消息安全模式和Windows帐户作为客户端凭据,因此尽管服务器和客户端在同一台计算机上,我们仍应在客户端上提供Windows凭据。
此外,请在配置文件中发布完整的System.servicemodel部分。 如果要修改配置,请优先修改服务器的绑定配置。
随时让我知道问题是否仍然存在。
已更新
我建议您将Nettcpbinding的安全模式明确指定为NONE

<bindings>
  <netTcpBinding>
    <binding name="willbeappliedontheendpoint">
      <security mode="None"></security>
    </binding>
  </netTcpBinding>
</bindings>

同时删除不相关的配置。
然后我怀疑该连接可能未正确关闭,请尝试在退出前手动在循环内关闭通信连接。
此外,我们还可以尝试使用ChannelFactory封装调用服务的函数。
https://docs.microsoft.com/zh-cn/dotnet/api/system.servicemodel.channelfactory-1?view=netframework-4.8
最后,请参考下面的链接,希望它会有用。
套接字连接已中止-CommunicationException

我设法解决了这个问题。 以下是我的问题和解决方案的简短总结。

问题总结:我创建了一个WCF服务,该服务配置为nettcpbinding。 我有一个包含dll的客户端,该客户端被构建为clr控制台应用程序(dll包含客户端的app.config和使用添加服务引用创建的客户端代理)。 客户端具有带while循环的功能,该功能通过服务请求值。 随着客户端的长时间运行,我的服务抛出了通信异常。

问题的解决方案:我使用svcUtil.exe创建了一个新的代理,其中包含用于关闭和打开通道的方法。 因此,在函数中,我创建了客户端类的新实例,并在函数的开头和结尾打开和关闭通道。 此外,为了不向服务发出太多请求,我让线程在while循环中休眠。

在主函数之后,我还创建了一个新实例以供进一步的请求。 这解决了我的问题。 我的客户端中的函数代码如下所示:

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的新手,因此这种方法对我有效,并解决了我的问题。 针对此问题的回调事件可能是一种更好的方法(请参阅链接)。

通过WCF进行回调事件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM