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