2010-08-09 3 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 (это CUSTOM OBJECT), и это свойство содержит список FuturesLinesAssets.
  • Смотрите ниже:

Родитель:

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

Как вы получаете от «Ошибка сокета» до круговой ссылки? У вас есть сообщение об ошибке, которое вы могли бы добавить в сообщение? –

+0

Потому что, когда я googled сообщение об ошибке, я получил много результатов, говоря о круговых ссылках. Кроме того, ошибка возникает только при попытке отправки ALOT данных, в противном случае она работает нормально. – Goober

ответ

11

это исключение не относится к циркуляру Reference, это просто чисто таймаут, как вы пытаетесь накапливать тонны данных по проводу.

Значения по умолчанию, которые поставляются с WCF, очень низок (они были изменены в WCF 4, я считаю). У чтения этих двух постов в блоге, они должны дать вам представление о том, как dethrottle вашим услугам:

Creating high performance WCF services

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

Update: также существует целый ряд различных тайм-аутов в конфигурации WCF и в зависимости от того, является ли это клиентом или сервером, о котором вы говорите, вам нужно обновить другое предложение тайм-аута ... прочитайте это thread о том, что каждый из них означает, и вы должны выяснить, какой из них вам нужен поднять. Или, вы можете просто установить каждый таймаут на int.max, если вам все равно, если вызов может занять некоторое время.

+0

ФАНТАСТИЧЕСКИЙ ВАМ БЫЛ ПРАВИЛЬНЫЙ МОЙ ХОРОШИЙ ЧЕЛОВЕК! – Goober

+0

Черт, 2-я ссылка мертва. – Gallen

+0

Есть ли зеркало для второго канала? – CodeSlinger512

13

Эта ошибка может быть вызвана несколькими обстоятельствами. Хотя в этом случае это была проблема синхронизации, она обычно не имеет ничего общего с таймингом, , особенно если ошибка получена немедленно. Возможными причинами являются:

  • Объекты, используемые в качестве параметров или возвращаемых типов в вашем контракте, не имеют конструкторов без параметров и не украшены атрибутом DataContract. Проверьте классы, используемые в качестве параметров или возвращаемых типов, а также все типы, используемые общедоступными свойствами этих классов. Если вы реализуете конструктор с параметрами для одного из этих классов, компилятор больше не будет добавлять конструктор без параметров по умолчанию, поэтому вам нужно будет добавить это самостоятельно.
  • Пределы по умолчанию, определенные в конфигурации службы, слишком низки (MaxItemsInObjectGraph, MaxReceivedMessageSize, MaxBufferPoolSize, MaxBufferSize, MaxArrayLength).
  • Некоторые общедоступные свойства объектов DataContract доступны только для чтения. Убедитесь, что все общедоступные свойства имеют как получатели, так и сеттеры.
+0

У меня была эта ошибка с объектом возврата, содержащим свойства с десятичными запятыми, выходящими за пределы и перечислениями с недопустимыми значениями. – pauloya

+1

Передача 'DataTable' через' .TableName' или пустую таблицу без данных ('new DataTable()') также может вызвать это. –

+2

У меня была эта ошибка, и основной причиной был WCF. Когда я отключился от WCF, проблема исчезла. – pettys

2

Была ли эта проблема длинным процессом инициализации, который вызывался из события OnStart установщика Windows Service Host. Исправлено установкой режима безопасности и тайм-аутов для привязки 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, когда вы его используете. В нашей системе мы используем одноразовый шаблон вместе с переносом всех вызовов функций в систему, чтобы обеспечить правильную очистку и протоколирование. Мы используем версию следующего класса:

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, позволяя им сначала обеспечить ведение журнала при всех ошибках, а во-вторых, чтобы гарантировать, что канал закрыт, когда ошибки не возникают, а прерываются, если происходит исключение. Наконец, поскольку он используется в заявлении using, вызывается окончательное удаление канала. Таким образом, будут предотвращены ошибки, возникающие из-за неправильной очистки каналов, которые будут выглядеть как эта ошибка.