0

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

  • What does the call-stack look like and what is the full exception(so including any inner exceptions). Feel free to [edit] that in. – rene Jul 31 '19 at 14:48
  • I hope with the screenshot I provided you with the information that you need. – bastikoch11 Aug 01 '19 at 07:04
  • When that exception occurs (looks like socket error) can you run from the command prompt `netstat -a -p tcp` and tell us how many ports are in TIME_WAIT? You might want to try to lower TcpTimedWaitDelay: https://learn.microsoft.com/en-us/biztalk/technical-guides/settings-that-can-be-modified-to-improve-network-performance if there are a lot (read hundreds or more) – rene Aug 01 '19 at 11:09
  • Configure WCF tracing with full message logging on the server side: https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/recommended-settings-for-tracing-and-message-logging – rene Aug 01 '19 at 11:44
  • Please refer to my updated question. Sorry for the late response, but it took me some time to implement that. – bastikoch11 Aug 02 '19 at 11:41

2 Answers2

0

What is the error details?
Since the Nettcpbinding uses message security mode and Windows account as the client credential by default, so we should provide the windows credential on the client-side although the server and the client is on the same machine.
Besides, please post the complete System.servicemodel section in the configuration file. If you want to modify the configuration, please take preference to modify the binding configuration of the server.
Feel free to let me know if the problem still exists.
Updated.
I recommend that you explicitly specify the security mode of the Nettcpbinding as NONE.

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

Also remove unrelated configurations.
Then I suspect that the connection may not be closed properly, please try to manually close the communication connection within the loop before exiting.
In addition, we can also try using ChannelFactory to encapsulate the function that invoking the service.
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.channelfactory-1?view=netframework-4.8
Finally, please refer to the link below, hoping it will be useful.
The socket connection was aborted - CommunicationException

Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
  • I posted the entire configuration file of the host and the client. The problem still exists, unfortunately. – bastikoch11 Aug 01 '19 at 07:03
  • what is the complete error message? you client-side seems not based on C#. Would you mind sharing more details about your client-side? Could we call the service by using ChannelFactory? Does it report errors when we use while(true) loop? – Abraham Qian Aug 01 '19 at 07:32
  • My client is a clr console application that consumes the service with a dll. This .dll includes the Service Reference and the app.config of the client. Such a design is mandatory, because I have some source files that are written in C++ and that I need to some calculations. To bring the C++ source files and the WCF Service together I created a CLR console application which lets me consume the service and use the c++ source files. I uploaded the complete error message. It reports the error directly after leaving the while loop, trying to use the same method again of the wcf-service. – bastikoch11 Aug 01 '19 at 11:04
  • Your update describes my problem very well. My service works fine if my client is only running for around 30 mins. If it runs for 2h or more, which means the while loop makes a lot of requests, the exception appears. My idea was to close the channel when the while loop is left and then open it again afterwards. But how can I do that? Another idea is to let the thread sleep in the while loop to make less requests. Does this bring any advantage at all? My ideas are shown in the update of my question. – bastikoch11 Aug 02 '19 at 07:52
  • Your idea is great. Hopefully that will solve the problem. Accessing the service by using a channel factory or a client proxy class, we all need a client object that has methods to open and close channels (connections). – Abraham Qian Aug 02 '19 at 08:41
  • Sorry for the late reply, but since I am new to wcf it took me a bit more time to create a proxy class. I created a proxy class (HMI_IPCClient) with svcutil and now I can open and close Client channels. I have the proxy compiled as a dll which I enclude in my CLR console applications. The problem is that the error still occurs. Another problem could be that I create in every .cpp file my own object of the proxy class. That may be a problem, too. The question is how I can make that object global?! – bastikoch11 Aug 06 '19 at 08:38
0

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