WCF, двусторонний обратный вызов, recieveTimeout netTcpBinding - PullRequest
5 голосов
/ 12 мая 2010

У меня есть служба WCF хост / клиент и клиент, который использует netTcpBinding и метод обратного вызова.

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

Proxy

[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 клиент переходит в состояние сбоя и закрывает клиент, прослушивающий обратный вызов.

Я вижу падение порта прослушивания, используя TCPVIEW от sysinternals.

Если я поддерживаю канал занятым, тайм-аут не срабатывает, поэтому это не является ошибкой в ​​сообщении WCF для сервера / клиента, так как несколько сообщений будут проходить нормально.

Я думал, что receiveTimeout был разработан, чтобы обеспечить способ определить, не получен ли ответ от сообщения WCF по TCP? Почему это нарушает связь. Похоже, что если для периода ожидания не было создано ни одного объекта обратного вызова, канал закрывается?

Что я делаю не так?

Ответы [ 3 ]

6 голосов
/ 14 мая 2010

Кажется, что истечение времени ожидания приводит к сбою службы хоста обратного вызова после того, как она достигает своего максимального количества. Что составляет 23,59 часа или по умолчанию 1 минута. Я могу решить проблему тайм-аута, установив для параметра receivetimeout значение Infinate

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

Но теперь мне интересно, действительно ли я использую правильный инструмент в WFC для связи между сервером и клиентом. Я хочу, чтобы хост / сервер работал на файловом сервере, и к нему было подключено несколько удаленных клиентов. Клиент будет пинговать сервер с помощью пульса, и иногда сервер может отправлять команду клиенту. Я делал это с remoting или tcpsockets и использовал «метод опроса клиента», где команды находились в очереди в базе данных и когда клиент опрашивал сервер на наличие команды каждые 10 минут, если для этого уникального клиента была ожидающая команда Это. Это работало хорошо, и имело преимущество НЕ иметь 1000 открытых соединений сокета tcp с сервером, поскольку клиент будет только случайным образом подключаться и отключаться. НО я решил попробовать WCF (в конце концов, разве это не новая новинка в Greates, заменяющая Remoting?), И когда я нашел Duplex, я подумал, я бы использовал его .... ТЕПЕРЬ, я думаю, что упускаю из виду, для чего нужен WCF Duplux ???

Помогите, я здесь упускаю понятия ???

4 голосов
/ 29 июля 2010

Значение, при котором установлено значение receiveTimeout, сообщит службе, как долго ждать, пока не произойдет сбой в канале связи, когда не получено сообщение приложения. Вы всегда можете увеличить это значение тайм-аута до большего числа (по умолчанию 10 минут), но вам также придется увеличить тайм-аут неактивности сеанса. Пожалуйста, см. http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.receivetimeout.aspx для получения дополнительной информации об обоих этих таймаутах.

Когда срабатывает тайм-аут приема или неактивности, дуплексный канал неисправен. Вам нужно будет создать новый прокси на стороне клиента, чтобы снова иметь возможность общаться с сервером.

Вы всегда можете проверить состояние подключения к каналу на стороне клиента, прежде чем пытаться вызвать сервер. Если CommunicationState канала не открыт, то вы можете создать новый прокси перед вызовом сервера.

3 голосов
/ 12 мая 2010

Вы пытались использовать DuplexChannelFactory в создании прокси (клиент)? Вот как это используется (замените создание, используя новый 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 вы можете использовать Service Trace Viewer - Microsoft Windows SDK, обычно в C: \ Program Files \ Microsoft SDKs \ Windows \ v6.0A \ bin \ SvcTraceViewer.exe

...