web-dev-qa-db-ja.com

ソケット接続は中止されました-CommunicationException

元々:

  • これは循環参照の問題だと思った........ではないことが判明した。
  • 問題は、サービス構成をまったく構成しなかったことから生じました。
  • デフォルトは非常に低いため、大量のデータを送信するとサービスが崩壊します。

シナリオ:

  • 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<string, FuturesLineAsset> FuturesLineDictionary { get; set ; }
}

思考:

  • タイプがBindableDictionary(THIS IS A CUSTOM OBJECT))のプロパティを持ち、そのプロパティがFuturesLinesAssetsのリストを保持しているFuturesAssetクラスを持っているからだろうか。
  • 下記参照:

親:

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

この例外は、循環参照とは関係ありません。大量のデータをネットワーク経由で送信しようとすると、純粋にタイムアウトします。

WCFに付属するデフォルト値は非常に低い(これらはWCF 4で変更されたと思う)。次の2つのブログ投稿を読んでください。サービスのスロットルを解除する方法についてのアイデアが得られるはずです。

高性能WCFサービスの作成

Wcfサービスを調整し、DoS攻撃を防ぎ、Wcfのスケーラビリティを維持する方法

Update:また、WCF構成には多数の異なるタイムアウトがあり、それがあなたが話しているクライアントまたはサーバーであるかどうかに応じて、更新する必要があります別のタイムアウト句...これを読んでください thread それぞれが何を意味するかについて、あなたはあなたがどれを上げる必要があるかを理解できるはずです。 または、呼び出しが完了するまでに長い時間がかかるかどうかを本当に気にしない場合は、すべてのタイムアウトをint.maxに設定することができます。

12
theburningmonk

このエラーは、さまざまな原因で発生する可能性があります。この場合はタイミングの問題でしたが、通常はタイミングとは関係ありません特にエラーがすぐに受信された場合。考えられる理由は次のとおりです。

  • コントラクトでパラメーターまたは戻り値の型として使用されるオブジェクトには、パラメーターなしのコンストラクターがなく、DataContract属性で装飾されていません。パラメーターまたは戻り値の型として使用されるクラスをチェックしますが、それらのクラスのパブリックプロパティによって使用されるすべての型もチェックします。これらのクラスのいずれかのパラメーターを使用してコンストラクターを実装する場合、コンパイラーはデフォルトのパラメーターレスコンストラクターをもう追加しないため、自分で追加する必要があります。
  • サービス構成で定義されているデフォルトの制限が低すぎます(MaxItemsInObjectGraph、MaxReceivedMessageSize、MaxBufferPoolSize、MaxBufferSize、MaxArrayLength)。
  • DataContractオブジェクトの一部のパブリックプロパティは読み取り専用です。すべてのパブリックプロパティにゲッターとセッターの両方があることを確認してください。
19
Adrian T

Windows Service Hostインストーラーの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);
3
Adrian Holmes

この問題は、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メソッドでラップされ、最初にすべてのエラーでログが記録されることを確認し、次にエラーが発生しない場合にチャネルが閉じられ、例外が発生すると中止されるようにします。最後に、usingステートメントにあるように、チャネルの最終処分が呼び出されます。このようにして、チャネルが適切にクリーンアップされないために発生するエラー(このエラーのように見える)は防止されます。

2
Jon Ediger

この例外は、IEnumerableコレクションを含むオブジェクトを返しているときに発生し、コレクションメンバーの1つが取得されているときに例外が発生しました。その時点で、コードでキャッチするのは遅すぎます。おそらく、WCFは、結果をストリーミングし始めているため、クライアントに例外を報告するには遅すぎるため、その場合はソケットを切断するように設計されています。

1
AndyH

WCFエラー:

ソケット接続は中止されました。これは、メッセージの処理エラー、リモートホストによる受信タイムアウトの超過、または基になるネットワークリソースの問題が原因である可能性があります。ローカルソケットタイムアウトは...

報告されるタイムアウトが1分に非常に近い場合(例:00:00:59.9680000)または正確に1分(つまり00:01:00)は、メッセージが大きすぎて バインディングの設定を超えている が原因である可能性があります。

これは、設定ファイルの値を増やすことで修正できます。例:

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

(例の値のみ、調整することができます)。

0
SharpC

私の場合、net tcpでWcfをインスタンス化しようとしていました。したがって、web.configのバインディングセクションに、「netTcpBinding」がこのように構成されている場合

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

次に、サービスインターフェイスの名前空間を使用して、コントラクト属性でエンドポイントを定義するサービスセクションを構成し、baseAddresも配置する必要があります。

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

私はこの問題に2日間を費やしましたが、これが私のために働いた唯一のことでした。

0
karique