2010-08-09 53 views
16
的CommunicationException

原:套接字连接被中止 -

  • 我认为这是一个循环引用问题........原来事实并非如此。
  • 问题在于根本没有配置服务配置。
  • 由于默认值非常低,发送大量数据将导致服务崩溃。

场景:

  • 看来我可以在我的WCF服务循环引用,但使用 “[DataContract(IsReference =真)”,无助于帮助解决问题。
  • 我收到错误“套接字连接被中止,这可能是由于处理您的消息时发生错误或远程主机超出接收超时或基础网络资源问题所致,本地套接字超时为'00:01 :00' “。
  • 我错过了什么吗?

代码:

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

    [DataMember] 
    public string EventData { get; set; } 

    [DataMember] 
    public SerializableDictionary<string, FuturesLineAsset> FuturesLineDictionary { get; set ; } 
} 

思考:

  • 我不知道这是因为我有一个类FuturesAsset,有类型的属性BindableDictionary(这是自定义OBJECT),并且该财产持有FuturesLines资产列表。
  • 见下文:

家长:

public class FuturesAsset 
{ 
    public string AssetName { get; set; } 
    public BindableDictionary<string, FuturesLineAsset> AssetLines { get; private set; } 

    public FuturesAsset() 
    { 
     AssetLines = new BindableDictionary<string, FuturesLineAsset>(); 
    } 

    public FuturesAsset(string assetName) 
    { 
     AssetLines = new BindableDictionary<string, FuturesLineAsset>(); 
     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; 
    } 
} 
+0

你如何从'套接字错误'获得循环引用?你有没有可以添加到帖子的错误信息? – 2010-08-09 16:15:43

+0

因为当我搜索错误消息时,我得到了许多关于循环引用的结果。此外,错误只发生在我尝试发送ALOT数据时,否则它工作正常。 – Goober 2010-08-09 16:17:27

回答

11

该异常是不相关的循环引用,它只是单纯的超时,当你试图通过电线抽取大量数据。

WCF附带的默认值非常低(我相信这些在WCF 4中已被更改)。有一个阅读这两个博客,他们应该给你如何dethrottle服务的想法:

Creating high performance WCF services

How to throttle a Wcf service, help prevent DoS attacks, and maintain Wcf scalability

更新:同样,也有许多不同的超时WCF配置,并根据它是你所说的客户端还是服务器,你需要更新一个不同的超时条款......阅读这个thread每一个都意味着什么,你应该能够找出你需要哪一个碰撞。 ,如果您不确定呼叫是否需要花费很长时间才能完成,则可以将每个超时设置为int.max。

+0

很奇怪你是否正确我的好人! – Goober 2010-08-09 17:01:02

+0

哎呀,第二个链接已经死了。 – Gallen 2013-09-21 14:31:26

+0

第二个链接是否有镜像? – CodeSlinger512 2013-11-21 21:16:53

13

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

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

我有这个错误与返回对象包含小数超出边界和枚举与无效值的属性。 – pauloya 2013-11-15 15:03:53

+1

传递'DataTable'通过没有'.TableName',或没有数据的空表('new DataTable()')也可以导致这种情况。 – 2014-02-24 19:13:09

+2

我有这个错误,根本原因是WCF。当我离开WCF时,问题消失了。 – pettys 2015-04-24 17:58:16

2

有一个长时间的初始化过程出现此问题,该过程正在从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); 
0

的WCF错误:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was ...

其中报道超时非常接近为1分钟(例如00:00:59.9680000)或1分钟恰好(即00:01:00)可以通过该消息过大和exceeding the settings for the binding引起。

这可以通过在配置文件中增加值是固定的,例如:

<binding name="MyWcfBinding" 
     maxReceivedMessageSize="10000000" 
     maxBufferSize="10000000" 
     maxBufferPoolSize="10000000" /> 

(例如只值,您可能会需要调整它们)。

1

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

0

此问题也可能是由于在完成使用WCF客户端时未清理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<T>(Func<T> 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方法进行包装,允许他们首先确保记录发生在所有错误上,其次确保通道在没有错误发生时关闭,但在发生异常时中止。最后,因为它在使用声明中,所以调用频道的最终处理。通过这种方式,可以防止由于通道未正确清理而出现的错误(看起来像这样的错误)。