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

时间:2017-07-21 19:29:53

标签: c# asp.net sockets wcf

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

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

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

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

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

    除了关闭连接之外,还要对服务器进行一些更改 在此post

  • 中描述

的疑问: 有没有比我提议的更好的选择?如果没有,您认为哪一个最好?

谢谢大家!

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

1 个答案:

答案 0 :(得分:0)

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

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