I've got a problem with the NetTcpBinding's Open, Send, Recive and Close timeouts on the initial call([OperationContract(IsOneWay = true, IsInitiating = true)]
)
Currently I'm trying to connect to a given IPAddress and if it fails I will connect to a different address.
This is because I cannot connect to my own server through my external IP (due to NAT Loopback on my router?), and instead of having 2 versions (one for the public and one for myself) I use a Try-Catch system which tries to connect to my external IP, if it works -> continue, if it fails -> try local IP -> continue.
The problem however is the timeout values. Since I am waiting for an exception to be thrown and caught, I need to lower this value as much as possible (preferred 5sec) instead of the default ~20 seconds.
I've tried to set these values on both Client and Server side
tcpBinding.OpenTimeout = new TimeSpan(0, 0, 5);
tcpBinding.CloseTimeout = new TimeSpan(0, 0, 5);
tcpBinding.SendTimeout = new TimeSpan(0, 0, 5);
tcpBinding.ReceiveTimeout = new TimeSpan(0, 0, 5);
Server side setup:
svh = new ServiceHost(typeof(ServiceAssembly.ServiceImplementation));
NetTcpBinding tcpBinding = new NetTcpBinding();
tcpBinding.MaxConnections = 100;
tcpBinding.MaxBufferPoolSize = (int)4096000;
tcpBinding.MaxBufferSize = 4096000;
tcpBinding.MaxReceivedMessageSize = (int)4096000;
tcpBinding.OpenTimeout = new TimeSpan(0, 0, 5);
tcpBinding.CloseTimeout = new TimeSpan(0, 0, 5);
tcpBinding.ReceiveTimeout = new TimeSpan(0, 0, 5);
tcpBinding.SendTimeout = new TimeSpan(0, 0, 5);
tcpBinding.ReliableSession.Ordered = true;
tcpBinding.TransactionFlow = false;
tcpBinding.Security.Transport.ProtectionLevel =
System.Net.Security.ProtectionLevel.EncryptAndSign;
tcpBinding.Security.Transport.ClientCredentialType =
TcpClientCredentialType.Windows;
tcpBinding.Security.Mode = SecurityMode.None;
svh.AddServiceEndpoint(typeof(ServiceAssembly.IChat),tcpBinding,"net.tcp://IPAddress:3100/MyService");
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
svh.Open();
Client side setup & call
InstanceContext context = new InstanceContext(callback);
NetTcpBinding tcpBinding = new NetTcpBinding();
tcpBinding.MaxConnections = 100;
tcpBinding.MaxBufferPoolSize = (int)4096000;
tcpBinding.MaxBufferSize = 4096000;
tcpBinding.MaxReceivedMessageSize = (int)4096000;
tcpBinding.TransactionFlow = false;
tcpBinding.OpenTimeout = new TimeSpan(0, 0, 5);
tcpBinding.CloseTimeout = new TimeSpan(0, 0, 5);
tcpBinding.SendTimeout = new TimeSpan(0, 0, 5);
tcpBinding.ReceiveTimeout = new TimeSpan(0, 0, 5);
tcpBinding.ReliableSession.Ordered = true;
tcpBinding.Security.Transport.ProtectionLevel =
System.Net.Security.ProtectionLevel.EncryptAndSign;
tcpBinding.Security.Transport.ClientCredentialType =
TcpClientCredentialType.Windows;
tcpBinding.Security.Mode = SecurityMode.None;
try
{
scf = new DuplexChannelFactory<IChat>(context, tcpBinding,
"net.tcp://" + m_ipAddress + ":" + m_port + "/MyService");
s = scf.CreateChannel();
s.Connect(client); <- First connection
}
catch
{
try
{
scf = new DuplexChannelFactory<IChat>(context, tcpBinding,
"net.tcp://" + m_localAddress + ":" + m_port + "/MyService");
s = scf.CreateChannel();
s.Connect(client);
m_ipAddress = m_localAddress;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
But the timeout for the exception to be thrown is still around 20 seconds. Changing these values wont change the time until the exception is thrown. I have added an image below to show the call stack.
Any advice on how to do fix this or even make it better is wanted.
The solution I found that helped me - not to remove this timeout, but to connect to my own server if local and/or connect over external IP if not - was to actually look for the process itself. If found -> Connect locally , else -> connect via the given IP. This does not answer my actual question - however - it does solve my initial issue. It seems that the TimeOut "delay" is due to the DNS and not something I can do to prevent it.
Here's my solution code if anyone's interested.
if (Process.GetProcessesByName("ProcessName").Length > 0)
isLocal = true;
if (isLocal)
scf = new DuplexChannelFactory<IChat>(context, tcpBinding,
"net.tcp://" + m_localAddress + ":" + m_port + "/MyService");
else
scf = new DuplexChannelFactory<IChat>(context, tcpBinding,
"net.tcp://" + m_ipAddress + ":" + m_port + "/MyService");