2010-08-09 90 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方法進行包裝,允許他們首先確保記錄發生在所有錯誤上,其次確保通道在沒有錯誤發生時關閉,但在發生異常時中止。最後,因爲它在使用聲明中,所以調用頻道的最終處理。通過這種方式,可以防止由於通道未正確清理而出現的錯誤(看起來像這樣的錯誤)。