Search code examples
c#wcfclrnettcpbindingcommunicationexception

WCF Service - Client receiving CommunicationException after many requests to localhost


I set up a WCF Service that is based on NetTcpBinding and I am using localhost. Client and Host run on same machine. I get a communication exception in the client consuming a specific method of the interface of the WCF Service in a while loop. The while loop is mandatory, because I am monitoring a value and action depends on change in value. The client is a clr console application and contains a dll with the service reference and the app.config file for the client.

For trying to solve the problem I increased the openTimeout, closeTimeout, receiveTimeout, sendTimeout, maxBufferPoolSize and maxReceivedMessageSize in the binding configurations, but without any success.

I also let the thread of the client sleep so that the method of the interface is less often called, but also without any success.

To give you an idea, below you can find the while loop of the client that calls the method of the interface. I also attached the binding configurations of the client.

While loop:

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

My question now is how to solve this problem? Is there any possibility that I empty the buffer of the requests? How can I avoid this Communication Exception?

Update 01/08/2019:

complete App.config file of Host:

  <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>

complete App.config file of the Client:

    <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>

And here I attached a screenshot of the Server stack trace:

Server stack trace

The complete error message of the client is: "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'."

I didn't handle the exception on the client side which gives me the following error message in my clr console application.

Error message of client

Update 02/08/2019:

The following code shows the idea of letting the thread sleep to avoid many requests:

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

The other idea is to integrate a method where I can cut the wire after the while loop and to open it again for further use.

Update 02/08/2019:

I enabled the WCF tracing as required and I could get the following exception details from the tracing (see screenshot and the translation below of the message):

"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


Solution

  • I managed to solve the problem. Below is a short sum up of my problem and the solution.

    Sum up of problem: I created a WCF Service that is configurated as nettcpbinding. I have a client that includes a dll and is built as a clr console application (dll contains the app.config of the client and the client proxy created with add service reference). The client has a function with a while loop requesting a value via the service. With long run times of the client my service throws a communication exceptions.

    Solution of the problem: I created a new proxy using svcUtil.exe that contains methods to close and open the channel. So in my function I create a new instance of my client class and open and close the channel in the beginning and in the end of the function. Furthermore, I let the thread sleep in the while loop in order not making so many requests to the service.

    After the function in the main I also create a new instance for further requests. This solved my problem. The code of the function in my client is shown below:

    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());
    

    Since I am new to WCF this approach works for me and solved my problem. Callback events for this problem may be a better approach (see link).

    Callback events via WCF