C# WCF NetTcpBinding 超时不工作
C# WCF NetTcpBinding timeout not working
我遇到了 NetTcpBinding 在初始调用时的打开、发送、接收和关闭超时问题([OperationContract(IsOneWay = true, IsInitiating = true)]
)
目前我正在尝试连接到给定的 IP 地址,如果失败,我将连接到另一个地址。
这是因为我无法通过我的外部 IP 连接到我自己的服务器(由于我的路由器上的 NAT 环回?),而不是有 2 个版本(一个用于 public,一个用于我自己)我使用 Try-捕获尝试连接到我的外部 IP 的系统,如果它有效 -> 继续,如果它失败 -> 尝试本地 IP -> 继续。
但是问题是超时值。由于我正在等待抛出和捕获异常,因此我需要尽可能降低此值(首选 5 秒)而不是默认的 ~20 秒。
我尝试在客户端和服务器端设置这些值
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);
服务器端设置:
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();
客户端设置和调用
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);
}
}
但是抛出异常的超时时间还在20秒左右。更改这些值不会更改抛出异常之前的时间。我在下面添加了一张图片来显示调用堆栈。
需要任何关于如何解决这个问题甚至让它变得更好的建议。
我发现对我有帮助的解决方案 - 不是删除此超时,而是连接到我自己的服务器,如果本地 and/or 通过外部 IP 连接,如果不是 - 是实际寻找进程本身。如果找到 -> 本地连接,否则 -> 通过给定的 IP 连接。
这并没有回答我的实际问题 - 但是 - 它确实解决了我最初的问题。
似乎超时 "delay" 是由于 DNS 而不是我可以采取的措施来阻止它。
如果有人感兴趣,这是我的解决方案代码。
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");
我遇到了 NetTcpBinding 在初始调用时的打开、发送、接收和关闭超时问题([OperationContract(IsOneWay = true, IsInitiating = true)]
)
目前我正在尝试连接到给定的 IP 地址,如果失败,我将连接到另一个地址。
这是因为我无法通过我的外部 IP 连接到我自己的服务器(由于我的路由器上的 NAT 环回?),而不是有 2 个版本(一个用于 public,一个用于我自己)我使用 Try-捕获尝试连接到我的外部 IP 的系统,如果它有效 -> 继续,如果它失败 -> 尝试本地 IP -> 继续。
但是问题是超时值。由于我正在等待抛出和捕获异常,因此我需要尽可能降低此值(首选 5 秒)而不是默认的 ~20 秒。
我尝试在客户端和服务器端设置这些值
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);
服务器端设置:
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();
客户端设置和调用
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);
}
}
但是抛出异常的超时时间还在20秒左右。更改这些值不会更改抛出异常之前的时间。我在下面添加了一张图片来显示调用堆栈。
我发现对我有帮助的解决方案 - 不是删除此超时,而是连接到我自己的服务器,如果本地 and/or 通过外部 IP 连接,如果不是 - 是实际寻找进程本身。如果找到 -> 本地连接,否则 -> 通过给定的 IP 连接。 这并没有回答我的实际问题 - 但是 - 它确实解决了我最初的问题。 似乎超时 "delay" 是由于 DNS 而不是我可以采取的措施来阻止它。
如果有人感兴趣,这是我的解决方案代码。
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");