5

私は、netTcpBinding とコールバック メソッドを使用しているホスト/クライアント WCF サービスとクライアントを取得しました。

<bindings>
      <netTcpBinding>
        <binding name="tcp_Unsecured" receiveTimeout="00:01:00" sendTimeout="00:01:00">
          <security mode="None" />
          <reliableSession enabled="true" ordered="true" inactivityTimeout="00:10:00"/>
        </binding>
      </netTcpBinding>
</bindings>

プロキシー

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://dotnetaddict.dotnetdevelopersjournal.com/wcf.samples", ConfigurationName="AlarmServer", CallbackContract=typeof(AlarmServerCallback), SessionMode=System.ServiceModel.SessionMode.Required)]
public interface AlarmServer
{

    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://dotnetaddict.dotnetdevelopersjournal.com/wcf.samples/AlarmServer/RegisterAlarm")]
    void RegisterAlarm(System.DateTime alarmTime, string clientName, string reminderMessage);

    [System.ServiceModel.OperationContractAttribute(IsOneWay = true, Action = "http://dotnetaddict.dotnetdevelopersjournal.com/wcf.samples/AlarmServer/unRegisterAlarm")]
    void unRegisterAlarm(string clientName);

    [System.ServiceModel.OperationContractAttribute(IsOneWay = true, Action = "http://dotnetaddict.dotnetdevelopersjournal.com/wcf.samples/AlarmServer/broadcastMessage")]
    void broadcastMessage(string msg);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface AlarmServerCallback
{

    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://dotnetaddict.dotnetdevelopersjournal.com/wcf.samples/AlarmServer/SignalAlarm")]
    void SignalAlarm(string reminderMessage);

    [System.ServiceModel.OperationContractAttribute(IsOneWay = true, Action = "http://dotnetaddict.dotnetdevelopersjournal.com/wcf.samples/AlarmServer/displayMessage")]
    void displayMessage(string msg);
}

コールバックを持つクライアント インスタンス

public MainForm()
{
    InitializeComponent();
    InstanceContext context = new InstanceContext(new AlarmCallback());
    client = new AlarmServerClient(context);
}

私が抱えている問題は、バインディングの recieveTimeout がトリガーされた後、クライアントが障害状態になり、コールバックをリッスンしているクライアントを閉じることです。

sysinternals の TCPVIEW を使用して、リッスン ポートのドロップを確認できます。

チャネルをビジー状態にしておくと、タイムアウトがトリガーされないため、サーバー/クライアントへの WCF メッセージの障害ではありません。複数のメッセージが問題なく流れます。

receiveTimeout は、TCP を介した WCF メッセージからの応答が失敗したかどうかを検出する方法を提供するように設計されていると思いましたか? 接続に問題があるのはなぜですか。タイムアウト期間中に作成されたコールバック オブジェクトがない場合、チャネルは閉じられているように見えますか?

私は何を間違っていますか?

4

3 に答える 3

6

Receivetime out により、コールバック ホスト サービスが最大カウントに達した後に障害が発生するようです。これは 23.59 時間またはデフォルトの 1 分です。receivetimeout を Infinate に設定することでタイムアウトの問題を解決できます

 <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_AlarmServer" receiveTimeout="infinite" >
          <security mode="None" />        
        </binding>
      </netTcpBinding>
    </bindings>

しかし、これは、WFC でサーバー/クライアント通信に適切なツールを本当に使用しているかどうか疑問に思っています。ホスト/サーバーをファイル サーバー上で実行し、複数のリモート クライアントをそれに接続したいと考えています。クライアントはハートビートでサーバーに ping を送信し、場合によってはサーバーがクライアントにコマンドを送信することがあります。私はこれをリモーティングまたはtcpsocketsで実行し、「クライアントポーリング方法」を使用していました。コマンドはデータベースでキューに入れられ、クライアントが10分ごとにサーバーにコマンドをポーリングしたとき、その一意のクライアントに保留中のコマンドがあった場合それ。これは問題なく機能し、クライアントはランダムにのみ接続および切断するため、サーバーへの 1000 の開いている tcp ソケット接続がないという利点がありました。

ここに概念がありませんか???

于 2010-05-13T23:05:55.820 に答える
4

receiveTimeout が設定されている値は、アプリケーション メッセージが受信されない場合に、通信チャネルに障害が発生するまでの待機時間をサービスに通知します。このタイムアウト値はいつでも大きくすることができますが (デフォルトは 10 分)、セッションの非アクティブ タイムアウトも増やす必要があります。これら両方のタイムアウトの詳細については、 http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.receivetimeout.aspxを参照してください。

受信タイムアウトまたは非アクティブ タイムアウトが発生すると、デュプレックス チャネルに障害が発生します。サーバーと再度通信できるようにするには、クライアント側で新しいプロキシを作成する必要があります。

サーバーを呼び出す前に、クライアント側でチャネル接続ステータスをいつでも確認できます。チャネルの CommunicationState が開かれていない場合は、サーバーを呼び出す前に新しいプロキシを作成できます。

于 2010-07-28T21:23:19.217 に答える
3

プロキシの作成 (クライアント) でDuplexChannelFactoryを使用してみましたか? 使用方法は次のとおりです ( new AlarmServerClient(context)を使用して作成を置き換えます)。

AlarmServer proxy = new DuplexChannelFactory<AlarmServer>(context,"YourAlarmServerEndpoint").CreateChannel();

編集:ログを有効にしてトレースを分析します:

メッセージロギングとトレースを有効にすることで、チャネル通信を分析できます。

<system.diagnostics>
<sources>
  <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
    <listeners>
      <add type="System.Diagnostics.DefaultTraceListener" name="Default">
        <filter type="" />
      </add>
      <add name="ServiceModelMessageLoggingListener">
        <filter type="" />
      </add>
    </listeners>
  </source>
  <source name="System.ServiceModel" switchValue="Information,ActivityTracing"
    propagateActivity="true">
    <listeners>
      <add type="System.Diagnostics.DefaultTraceListener" name="Default">
        <filter type="" />
      </add>
      <add name="ServiceModelTraceListener">
        <filter type="" />
      </add>
    </listeners>
  </source>
</sources>
<sharedListeners>
  <add initializeData="Your_svclog_file_here"
    type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
    <filter type="" />
  </add>
  <add initializeData="Your_svclog_file_here"
    type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
    <filter type="" />
  </add>
</sharedListeners>
<trace autoflush="true" />

この場合、トレースは「情報」をログに記録できます。チャネルの作成を確認することが重要です。

svclog ファイルを分析するには、通常は C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe にある Service Trace Viewer - Microsoft Windows SDK を使用できます。

于 2010-05-12T16:15:12.460 に答える