套接字连接已中止 – CommunicationException

本来:

  • 我认为这是一个循环参考问题……..事实certificate它不是。
  • 问题产生于根本没有配置服务配置。
  • 由于默认值非常低,因此发送大量数据会导致服务崩溃。

场景:

  • 看来我的WCF服务中可能有循环引用,但使用“[DataContract(IsReference = true)]”,没有任何帮助解决它。
  • 我收到错误“套接字连接已中止。这可能是由于处理消息时出错或远程主机超出接收超时或基础网络资源问题引起的。本地套接字超时为’00:01:00′ “。
  • 我错过了什么吗?

码:

[DataContract(IsReference=true)] public class Message { [DataMember] public string TopicName { get; set; } [DataMember] public string EventData { get; set; } [DataMember] public SerializableDictionary FuturesLineDictionary { get; set ; } } 

思考:

  • 我想知道是不是因为我有一个FuturesAsset类,它有一个BindableDictionary类型的属性(这是一个CUSTOM OBJECT),该属性包含一个FuturesLinesAssets列表。
  • 见下文:

家长:

 public class FuturesAsset { public string AssetName { get; set; } public BindableDictionary AssetLines { get; private set; } public FuturesAsset() { AssetLines = new BindableDictionary(); } public FuturesAsset(string assetName) { AssetLines = new BindableDictionary(); AssetName = assetName; } } 

儿童:

 public class FuturesLineAsset { public string ReferenceAsset { get; set; } public string MID { get; set; } public double LivePrice { get; set; } public DateTime UpdateTime { get; set; } public DateTime LastContributedTime { get; set; } public double Spread { get; set; } public double Correlation { get; set; } public DateTime Maturity { get; set; } public double ReferenceCurve { get; set; } public FuturesLineAsset(string mID, string referenceAsset, double livePrice) { MID = mID; ReferenceAsset = referenceAsset; ReutersLivePrice = livePrice; } } 

该exception与循环引用无关,当您尝试通过线路抽取大量数据时,它只是完全超时。

WCF附带的默认值非常低(我相信这些在WCF 4中已经更改)。 阅读这两篇博客文章,他们应该让您了解如何解决您的服务:

创建高性能WCF服务

如何限制Wcf服务,帮助防止DoS攻击,并维护Wcf可伸缩性

更新 :此外,WCF配置中有许多不同的超时,并且取决于它是您正在谈论的客户端还是服务器,您需要更新不同的超时子句…请读取此线程的内容你应该能够弄清楚你需要碰到哪一个。 或者 ,您可以将每个超时设置为int.max,如果您真的不在乎呼叫是否需要很长时间才能完成。

这个错误可能是由许多事情引起的。 虽然在这种情况下这是一个时间问题,但它通常与时间无关, 特别是如果立即收到错误 。 可能的原因是:

  • 在合同中用作参数或返回类型的对象没有无参数构造函数,也没有使用DataContract属性进行修饰。 检查用作参数或返回类型的类,以及这些类的公共属性使用的所有类型。 如果使用其中一个类的参数实现构造函数,编译器将不再为您添加默认的无参数构造函数,因此您需要自己添加它。
  • 服务配置中定义的默认限制太低(MaxItemsInObjectGraph,MaxReceivedMessageSize,MaxBufferPoolSize,MaxBufferSize,MaxArrayLength)。
  • DataContract对象的某些公共属性是只读的。 确保所有公共属性都包含getter和setter。

从Windows服务主机安装程序的OnStart事件调用的长初始化过程中出现此问题。 通过设置TCP绑定的安全模式和超时来解决。

  // Create a channel factory. NetTcpBinding b = new NetTcpBinding(); b.Security.Mode = SecurityMode.Transport; b.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows; b.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign; b.MaxReceivedMessageSize = 1000000; b.OpenTimeout = TimeSpan.FromMinutes(2); b.SendTimeout = TimeSpan.FromMinutes(2); b.ReceiveTimeout = TimeSpan.FromMinutes(10); 

当我在其中返回包含IEnumerable集合的对象时,发生了此exception,并且在检索其中一个集合成员时发生了exception。 此时,在代码中捕获它已经太晚了,并且可能在这种情况下WCF被设计为断开套接字,因为向客户端报告exception也为时已晚,因为它已经开始流式传输结果。

此问题还可能是由于在完成使用后未清理WCF客户端。 在我们的系统中,我们使用一次性模式并将所有函数调用包装到系统中,以便进行适当的清理和记录。 我们使用以下类的版本:

  public class WcfWrapper : IDisposable { private readonly OperationContextScope _operationContextScope; private readonly IClientChannel _clientChannel; public WcfWrapper(IClientChannel clientChannel) { _clientChannel = clientChannel; _operationContextScope = new OperationContextScope(_clientChannel); } public void Dispose() { _operationContextScope.Dispose(); } public T Function(Func func) { try { var result = func(); _clientChannel.Close(); return result; } catch (Exception ex) { KTrace.Error(ex); _clientChannel.Abort(); throw; } } public void Procedure(Action action) { try { action(); _clientChannel.Close(); } catch (Exception ex) { KTrace.Error(ex); _clientChannel.Abort(); throw; } } } } 

我们在服务中进行的每个WCF调用都是通过一个定义的接口类,如下所示:

  public sealed class WcfLoginManager : ILoginManager { private static LoginManagerClient GetWcfClient() { return new LoginManagerClient( WcfBindingHelper.GetBinding(), WcfBindingHelper.GetEndpointAddress(ServiceUrls.LoginManagerUri)); } public LoginResponse Login(LoginRequest request) { using(var loginManagerClient = GetWcfClient()) using (var slice = new WcfWrapper(loginManagerClient.InnerChannel)) { DSTicket ticket; DSAccount account; return slice.Function(() => new LoginResponse(loginManagerClient.Login(request.accountName, request.credentials, out ticket, out account), ticket, account)); } } } 

使用此模式,系统中的所有WCF调用都包含Function或Procedure方法,允许它们首先确保在所有错误上进行日志记录,然后确保在没有错误发生时关闭通道,但如果发生exception则中止。 最后,正如在using语句中那样,调用最终的通道处理。 以这种方式,将防止由于未正确清理的通道而发生的错误,这将看起来像这个错误。

WCF错误:

套接字连接已中止。 这可能是由于处理消息时出错或远程主机超出接收超时或基础网络资源问题引起的。 本地套接字超时是……

报告的超时非常接近1分钟(例如00:00:59.9680000 )或1分钟(即00:01:00 )可能是由于消息太大而超出了绑定的设置 。

这可以通过增加配置文件中的值来修复,例如:

  

(仅示例值,您可能想要调整它们)。