3

my .NET 4.5 application uses WCF net.tcp binding to cummunicate with server. The communication is pretty simple. Client just invoke one method and server returns true/false. The server must respond in 5 seconds. If not the client tries another server. The timing is critical for me. WCF timeouts (Send, Recieve, Open, Close, Operation and ChannelInitializationTimeout) works fine when the PC with server is running. However when the PC is not running (or bad IP address is filled in config) it takes almost 30s until the exception is thrown. Is there any other timeout I must configure to get it working?

Here is my client code (nothing is placed in app.config file):

        NetTcpBinding binding = new NetTcpBinding(SecurityMode.None)
        {
            SendTimeout = TimeSpan.FromMilliseconds(Configuration.Instance.LocalConfiguration.Failover.SendTimeout),
            ReceiveTimeout = TimeSpan.FromMilliseconds(Configuration.Instance.LocalConfiguration.Failover.RecieveTimeout),
            OpenTimeout = TimeSpan.FromMilliseconds(Configuration.Instance.LocalConfiguration.Failover.OpenTimeout),
            CloseTimeout = TimeSpan.FromMilliseconds(Configuration.Instance.LocalConfiguration.Failover.CloseTimeout),
            TransactionFlow = false,
            TransactionProtocol = TransactionProtocol.Default,
            TransferMode = TransferMode.Buffered,
            Security = new NetTcpSecurity() { Mode = SecurityMode.None },
            ReliableSession = new OptionalReliableSession() { Enabled = false },
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() { MaxArrayLength = 16384, MaxBytesPerRead = 4096, MaxDepth = 32, MaxNameTableCharCount = 16384, MaxStringContentLength = 8192 },
            Name = "NoSecurity",
            MaxReceivedMessageSize = 65535,
            MaxConnections = 10,
            MaxBufferSize = 65535,
            MaxBufferPoolSize = 524288,
            ListenBacklog = 10,
            HostNameComparisonMode = HostNameComparisonMode.StrongWildcard
        };

        BindingElementCollection be = binding.CreateBindingElements();
        TcpTransportBindingElement tcpBe = be.Find<TcpTransportBindingElement>();
        tcpBe.ChannelInitializationTimeout = TimeSpan.FromMilliseconds(Configuration.Instance.LocalConfiguration.Failover.InitializationTimeout);
        tcpBe.TransferMode = TransferMode.Buffered;
        CustomBinding customBinding = new CustomBinding(be);

        FailoverClient.ListenerClient serviceClient = new FailoverClient.ListenerClient(customBinding, new EndpointAddress(address));
        serviceClient.InnerChannel.OperationTimeout = TimeSpan.FromMilliseconds(Configuration.Instance.LocalConfiguration.Failover.OperationTimeout);

ps: The exception thrown after 30s is 'System.ServiceModel.EndpointNotFoundException ... the attempt lasted for 00:00:04.123. TCP error 10060...' with nested exception 'System.Net.Sockets.SocketException ...the remote party did not properly respond after period of time...'

EDIT: I found a workaround, but it does not anwser my question. I can use asynchronous call and wait for completion.

        Task<bool> task = serviceClient.HeartbeatAsync();
        try
        {
            if (task.Wait(5000))
            {
                Console.WriteLine("Task result: " + task.Result);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
  • 1
    Are you sure that this config get's applied ? Did you check the running values on the service binding to make sure it get's set to 5 ? To my understanding the 4 config params should be enough https://msdn.microsoft.com/en-us/library/hh924831(v=vs.110).aspx – Marty Mar 07 '16 at 16:23
  • Well my guess there is problem at network layer....Routing protocols are the ones which determine how to reach a server...So all the neighbouring routers are queried for the IP adress and in case of correct IP or IP which does not have much hop, it takes very less time to determine the route but for the IP which is incorrect or down then neighbouring routers may cascade query to their neighbouirng routers and may add up to time to determine that no such server is availalbe. That explains time to takes but is there any configuration you can do so that it times out I am not sure about that.... – Viru Mar 07 '16 at 16:26
  • @Marty timeout values are only valid if there is successful connection to server and client waiting to response from server from more than specified interval. In this case, connection itself is not established and it takes quite time to find out that server is not available so OP is looking for configuration which determines that it should stop looking for server if not found within x seconds – Viru Mar 07 '16 at 16:29
  • Could you use something like [this]?(http://stackoverflow.com/questions/570098/in-c-how-to-check-if-a-tcp-port-is-available/724022#724022) – Dominic Cotton Mar 07 '16 at 16:45
  • Have you tried replacing your 'Failover' timeouts with explicit timespans for testing? Technically this should be handled by the openTimeout. Like this: http://stackoverflow.com/questions/10169569/wcf-callback-service-with-nettcp-binding-timeout-after-10-mins OR http://stackoverflow.com/questions/15044644/wcf-decrease-client-connection-timeout – MikeDub Mar 07 '16 at 22:44
  • Depends. What value is currently being set on `OpenTimeout`? Hard to tell from your code –  Mar 08 '16 at 04:17
  • 1) Thanks for clues, but I already tried these tricks. None of them works. 2) Yes, the configuration params are OK. I tried it with constants as well. – Miroslav Jasso Mar 08 '16 at 06:49
  • 3) The configuration is applied - when connecting to any live IP address (gateway for example) it throws exception after 5 seconds. – Miroslav Jasso Mar 08 '16 at 06:58

0 Answers0