wake-up-neo.com

Die Socket-Verbindung wurde abgebrochen - CommunicationException

Ursprünglich:

  • Ich dachte, dies sei ein Zirkelreferenzproblem ........ es stellt sich heraus, dass dies nicht der Fall ist.
  • Das Problem bestand darin, die Service-Konfigurationen überhaupt nicht konfiguriert zu haben.
  • Da die Standardwerte sehr niedrig sind, wird der Dienst durch das Senden vieler Daten zum Erliegen kommen.

Szenario:

  • Es scheint, dass ich in meinem WCF-Dienst möglicherweise Zirkelverweise habe. Die Verwendung von "[DataContract (IsReference = true)]" hilft jedoch nicht, das Problem zu beheben.
  • Ich erhalte den Fehler "Die Socket-Verbindung wurde abgebrochen. Dies könnte durch einen Fehler bei der Verarbeitung Ihrer Nachricht oder durch ein Überschreiten des Empfangs-Timeouts durch den Remote-Host oder durch ein zugrunde liegendes Problem mit der Netzwerkressource verursacht werden. Das lokale Socket-Timeout war '00: 01: 00 '. . "
  • Habe ich etwas verpasst?

Code:

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

Gedanken:

  • Ich frage mich, ob es sich um eine FuturesAsset-Klasse handelt, die eine Eigenschaft des Typs BindableDictionary (THIS IS A CUSTOM OBJECT) hat, und diese Eigenschaft enthält eine Liste von FuturesLinesAssets.
  • Siehe unten:

Elternteil:

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

Kind:

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;
    }
}
21
Goober

diese Ausnahme bezieht sich nicht auf Circular Reference. Es wird lediglich ein Timeout ausgeführt, wenn Sie versuchen, Tonnen von Daten über das Kabel zu pumpen.

Die mit WCF gelieferten Standardwerte sind sehr niedrig (diese Werte wurden meiner Meinung nach in WCF 4 geändert). Lesen Sie sich diese beiden Blogeinträge durch und sie sollten Ihnen eine Vorstellung davon geben, wie Sie Ihren Dienst drosseln können:

Hochleistungs-WCF-Dienste erstellen

Wie man einen Wcf-Dienst drosselt, DoS-Angriffe verhindert und die Wcf-Skalierbarkeit aufrechterhält

Update: Auch in der WCF-Konfiguration gibt es verschiedene Timeouts. Abhängig davon, ob Sie über den Client oder Server sprechen, müssen Sie eine andere Timeout-Klausel aktualisieren ... lesen Sie dies Thread was jedes davon bedeutet und Sie sollten herausfinden können, welches Sie aufstocken müssen. Oder, Sie könnten einfach jedes Timeout auf int.max setzen, wenn Sie sich nicht wirklich darum kümmern, ob ein Anruf längere Zeit in Anspruch nehmen kann.

12
theburningmonk

Dieser Fehler kann verschiedene Ursachen haben. Während es in diesem Fall ein Timing-Problem war, hat es normalerweise nichts mit Timings zu tun, insbesondere wenn der Fehler sofort empfangen wird. Mögliche Gründe sind:

  • Die in Ihrem Vertrag als Parameter oder Rückgabetypen verwendeten Objekte haben keine parameterlosen Konstruktoren und sind nicht mit dem DataContract-Attribut versehen. Überprüfen Sie die als Parameter oder Rückgabetypen verwendeten Klassen, aber auch alle von den öffentlichen Eigenschaften dieser Klassen verwendeten Typen. Wenn Sie einen Konstruktor mit Parametern für eine dieser Klassen implementieren, fügt der Compiler nicht mehr den standardmäßigen parameterlosen Konstruktor für Sie hinzu, so dass Sie diesen selbst hinzufügen müssen.
  • Die in der Servicekonfiguration definierten Standardgrenzwerte sind zu niedrig (MaxItemsInObjectGraph, MaxReceivedMessageSize, MaxBufferPoolSize, MaxBufferSize, MaxArrayLength).
  • Einige öffentliche Eigenschaften Ihrer DataContract-Objekte sind schreibgeschützt. Stellen Sie sicher, dass alle öffentlichen Eigenschaften über Getter und Setter verfügen.
16
Adrian T

Hatte dieses Problem mit einem langen Initialisierungsprozess, der vom OnStart-Ereignis eines Windows Service Host-Installationsprogramms aufgerufen wurde. Festgelegt durch Festlegen des Sicherheitsmodus und der Zeitüberschreitung für die TCP - Bindung.

            // 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);
3
Adrian Holmes

Dieses Problem kann auch darauf zurückzuführen sein, dass der WCF-Client nicht bereinigt wird, wenn Sie ihn nicht mehr verwenden. In unserem System verwenden wir das Einwegmuster und wickeln alle Funktionsaufrufe in das System ein, um eine ordnungsgemäße Bereinigung und Protokollierung zu ermöglichen. Wir verwenden eine Version der folgenden Klasse:

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

}

Jeder WCF-Aufruf, den wir in unseren Service aufnehmen, erfolgt über eine definierte Schnittstellenklasse wie die folgende:

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

Unter Verwendung dieses Musters werden alle WCF-Aufrufe in das System entweder mit der Function- oder der Procedure-Methode umschlossen. Dadurch können sie zunächst sicherstellen, dass die Protokollierung aller Fehler erfolgt, und zweitens, um sicherzustellen, dass der Kanal geschlossen wird, wenn keine Fehler auftreten, aber bei einer Ausnahme abgebrochen wird . Schließlich, da es sich in einer using-Anweisung befindet, wird die endgültige Verfügung des Kanals aufgerufen. Auf diese Weise werden Fehler, die durch nicht ordnungsgemäß bereinigte Kanäle entstehen, die wie dieser Fehler aussehen, vermieden.

2
Jon Ediger

Diese Ausnahmebedingung trat für mich auf, als ich ein Objekt mit IEnumerable-Auflistungen zurückgegeben habe und eine Ausnahmebedingung aufgetreten ist, während eines der Auflistungsmitglieder abgerufen wurde. Zu diesem Zeitpunkt ist es zu spät, um es in Ihrem Code einzufangen, und WCF ist vermutlich dafür ausgelegt, den Socket in diesem Fall zu trennen, da es auch zu spät ist, dem Client eine Ausnahme zu melden, da bereits mit dem Streaming der Ergebnisse begonnen wurde.

1
AndyH

Der WCF-Fehler:

Die Socket-Verbindung wurde abgebrochen. Dies kann durch einen Fehler verursacht werden Verarbeitung Ihrer Nachricht oder ein Empfangszeitlimit, das von der .__ überschritten wird. Remote-Host oder ein zugrunde liegendes Problem mit der Netzwerkressource. Lokaler Socket Timeout war ...

die angegebenen Timeouts liegen sehr nahe an 1 Minute (z. B. 00:00:59.9680000) oder genau 1 Minute (d. h. 00:01:00), weil die Nachricht zu groß ist und die Einstellungen für die Bindung überschreitet .

Dies kann durch Erhöhen der Werte in der Konfigurationsdatei behoben werden, z.

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

(Nur für Beispielwerte, möchten Sie sie möglicherweise anpassen).

0
SharpC

In meinem Fall habe ich versucht, eine Wcf mit net tcp zu instanziieren. Wenn Sie also im Bindungsbereich Ihrer web.config das "netTcpBinding" so konfiguriert haben

<bindings>
    <netTcpBinding>
        <binding name="bindingName" closeTimeout="01:10:00" openTimeout="01:10:00" receiveTimeout="01:10:00" sendTimeout="01:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647" portSharingEnabled="true">
            <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384"/>
            <reliableSession ordered="true" inactivityTimeout="01:10:00" enabled="false"/>
            <security mode="None"/>
        </binding>
    </netTcpBinding>
</bindings>

Anschließend müssen Sie den Serviceabschnitt konfigurieren, der die Endpunkte mit ihrem Vertragsattribut über den Namespace Ihrer Serviceschnittstelle definiert, und auch die baseAddres in etwa so einfügen

<services>
  <service behaviorConfiguration="sgiBehavior" name="Enterprise.Tecnic.SGI.OP.Wcf.OP">
    <endpoint address="" behaviorConfiguration="endPointBehavior" binding="webHttpBinding" bindingConfiguration="BindingWebHttp" name="endPointHttp" contract="Enterprise.Tecnic.SGI.OP.Interface.IOP"/>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <endpoint address="" binding="netTcpBinding" bindingConfiguration="bindingName"
      name="EndpointNetTcp" contract="Enterprise.Tecnic.SGI.OP.Interface.IOP" />

    <Host>
      <baseAddresses>
        <!--  <add baseAddress="http://localhost:61217/OP.svc"/> -->
        <add baseAddress="http://www.Enterprise.com/Tecnic/SGI/OP/" />
        <add baseAddress="net.tcp://www.Enterprise.com/Tecnic/SGI/OP/" />           
      </baseAddresses>
    </Host>
  </service>
</services>

Ich habe zwei Tage mit diesem Problem verbracht, aber das war das Einzige, was mir geholfen hat.

0
karique