导致 TCP/IP 端口耗尽的 C# WCF 连接



我正在处理一个 ASP.NET 的MVC项目,发现几个与WCF服务的连接没有关闭,我认为这导致了TCP/IP端口耗尽。

我在资源监视器/网络/TCP 连接处检查了服务器,有数千个灰色连接作为"IPV6 环回",并且在某些时候连接太多,服务器停止在服务端口上响应。

Exist是一个依赖注入,用于处理控制器上的连接,并且有一个"CloseChannel"方法,但没有调用它,我对它进行了一些更改并开始在控制器上的Dipose方法中调用它以关闭连接,但我没有得到任何结果。环回继续出现。

我认为要做的两个解决方案是:

  • 删除依赖注入并创建正常连接 每次使用。

    除了关闭连接之外,在服务器上进行一些更改,如 本文中描述

怀疑: 还有比我提出的更好的选择吗?如果没有,您认为哪一个是最好的?

谢谢大家!

PS.:今天用于打开和关闭连接的代码:

这在控制器上调用:

IClient wcfClient = WcfChannel.CreateChannel<IClient>(connectionstr, WcfChannel.WcfBinding.NetTcpBinding);

这是 WcfChannel:

public static class WcfChannel
{
public static T CreateChannel<T>(string endpointAddress, WcfBinding wcfBinding)
{
Binding binding = null;
#region ReaderQuotas
XmlDictionaryReaderQuotas readerQuotas = new XmlDictionaryReaderQuotas()
{
MaxDepth = int.MaxValue,
MaxStringContentLength = int.MaxValue,
MaxArrayLength = int.MaxValue,
MaxBytesPerRead = int.MaxValue,
MaxNameTableCharCount = int.MaxValue
};
#endregion
switch (wcfBinding)
{
case WcfBinding.BasicHttpBinding:
case WcfBinding.NetMsmqBinding:
case WcfBinding.NetNamedPipeBinding:
throw new NotImplementedException();
case WcfBinding.NetTcpBinding:
binding = new NetTcpBinding()
{
Name = "NetTcpBinding",
MaxBufferPoolSize = long.MaxValue,
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue,
ReaderQuotas = readerQuotas,
Security = new NetTcpSecurity() { Mode = SecurityMode.None },
CloseTimeout = new TimeSpan(0, 5, 0),
OpenTimeout = new TimeSpan(0, 5, 0),
ReceiveTimeout = new TimeSpan(0, 5, 0),
SendTimeout = new TimeSpan(0, 5, 0)
};
break;
case WcfBinding.NetTcpBindingStreamed:
binding = new NetTcpBinding()
{
Name = "NetTcpBindingStreamed",
TransferMode = TransferMode.Streamed,
MaxBufferPoolSize = long.MaxValue,
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue,
ReaderQuotas = readerQuotas,
Security = new NetTcpSecurity() { Mode = SecurityMode.None },
CloseTimeout = new TimeSpan(0, 5, 0),
OpenTimeout = new TimeSpan(0, 5, 0),
ReceiveTimeout = new TimeSpan(0, 5, 0),
SendTimeout = new TimeSpan(0, 5, 0)
};
break;
case WcfBinding.WS2007HttpBinding:
case WcfBinding.WSHttpBinding:
throw new NotImplementedException();
default:
throw new NotImplementedException();
}
EndpointAddress endpoint = new EndpointAddress(endpointAddress);
var channelFactory = new ChannelFactory<T>(binding, endpoint);
T channelObj = channelFactory.CreateChannel();
return channelObj;
}
public static void CloseChannel(this object obj)
{
if (obj != null)
{
try
{
(obj as IClientChannel).Close();
}
catch (CommunicationException)
{
if (obj.GetType().GetMethod("Abort") != null)
{
(obj as IClientChannel).Abort();
}
}
catch (TimeoutException)
{
if (obj.GetType().GetMethod("Abort") != null)
{
(obj as IClientChannel).Abort();
}
}
catch (Exception)
{
//many connections doesn't have and Abort or close
}

if (obj.GetType().GetMethod("Dispose") != null)
{
(obj as IDisposable).Dispose();
}
obj = null;
}
}
public enum WcfBinding
{
BasicHttpBinding,
NetMsmqBinding,
NetNamedPipeBinding,
NetTcpBinding,
NetTcpBindingStreamed,
WS2007HttpBinding,
WSHttpBinding
}
}

我怀疑您的问题是由未管理 WCF 会话的事实引起的。网络 TCP 绑定是基于会话的绑定,需要管理会话。与会话由服务器启动和管理的 ASP.NET 相反,在 WCF 中,会话由客户端启动和管理。 您可以使用 ServiceContract/SessionMode、OperationContract/IsInitiating/IsTerminating 注释属性来管理会话。(此处的文档:https://learn.microsoft.com/en-us/dotnet/framework/wcf/using-sessions(

在客户端,您需要在结束会话后调用 CloseChannel 方法。此外,还需要验证所有异常的通道状态并调用 abort 方法(此处有关使用网络 TCP 绑定客户端的一些注意事项:https://blogs.msdn.microsoft.com/rodneyviana/2016/02/29/considerations-for-nettcpbindingnetnamedpipebinding-you-may-not-be-aware/(。此外,在服务器端,作为最佳实践,可能希望启用服务限制以限制会话/服务实例 (https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-servicethrottlingbehavior-to-control-wcf-service-performance(。

最新更新