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