2010-05-12 17 views
5

Ive got a Host/Client WCF Service and client que está usando netTcpBinding y un método de devolución de llamada.WCF, Duplex callback, recieveTimeout 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 ejemplo

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

cliente con devolución de llamada

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

El problema que tengo es que después de la recieveTimeout unión desencadena, el cliente entra en un estado de fallo y cierra los clientes escuchar llamar de vuelta.

Puedo ver la caída del puerto de escucha usando TCPVIEW desde sysinternals.

Si mantengo el canal ocupado, el tiempo de espera no se dispara, por lo que no es un error en el mensaje WCF al Servidor/Cliente, ya que varios mensajes fluirán a través de Aceptar.

Pensé que el receiveTimeout fue diseñado para proporcionar una manera de detectar si una respuesta del mensaje WCF sobre TCP falló? ¿Por qué está fallando la conexión? Casi parece que si no hay ningún objeto de devolución de llamada creado para el período de tiempo de espera, entonces el canal se cierra?

¿Qué estoy haciendo mal?

+0

¿ha encontrado alguna solución a esto? –

Respuesta

2

¿Ha intentado utilizar un DuplexChannelFactory, en la creación de proxy (cliente)? Así es como se usa (en lugar de la creación usando nueva AlarmServerClient (contexto)):

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

EDIT: Habilitar registro para analizar trazas:

Su posible analizar la comunicación de los canales, permitiendo El registro de mensajes y localizar:

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

En este caso, el Trace puede registrar "Información". Es importante ver la creación de canales.

Para analizar el archivo svclog, puede utilizar el servicio de rastreo Visor - SDK de Microsoft Windows, normalmente en C: \ Archivos de programa \ Microsoft SDKs \ Windows \ v6.0A \ bin \ SvcTraceViewer.exe

+0

Lo intenté, no pareció ayudar. ¡Todavía estoy desconcertado! – PrimeTSS

+0

Ive también simplifica las ataduras y se deshizo de los tiempos muertos y las propiedades reliablesession Aún así, la llamada de vuelta canal entra en un " Estado de falla (¿le gustaría saber por qué y obtener más información sobre este error?) – PrimeTSS

+0

Al habilitar el registro, puede analizar dónde se está bloqueando la comunicación. ¡Espero eso ayude! – Erup

5

parece que el El tiempo de espera de recepción hace que el servicio de host de devolución de llamada provoque una falla después de que alcanza su recuento máximo. Que es 23.59 horas o el valor predeterminado de 1 minuto. que pueda resolverse el problema de tiempo de espera con el establecimiento de receivetimeout Infinate

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

Pero esto me tiene ahora preguntando si estoy realmente utilizando la herramienta adecuada en la CWF para las comunicaciones cliente/servidor. Quiero que un servidor/servidor se ejecute en un servidor de archivos y múltiples clientes remotos conectados a él. El cliente hará ping al servidor con un latido, y ocasionalmente el servidor podría enviar un comando al cliente. Estaba haciendo esto con remoting o tcpsockets y usando un "método de sondeo de cliente", donde los comandos estaban en una base de datos y cuando el cliente sondeó el servidor para un comando cada 10 minutos, si había un comando pendiente para ese cliente único que obtenía eso.Esto funcionó bien, y tenía la ventaja de NO tener 1000 conexiones de socket tcp abiertas en el servidor, ya que el cliente solo se conectaba y desconectaba al azar. PERO decidí probar WCF (después de todo, ¿no es esta la última versión en grandes reemplazos de Remoting?) Y cuando encontré Duplex pensé, Id usarlo ... AHORA estoy pensando que me falta el punto sobre qué es WCF Duplux ???

Ayuda ¿Echo de menos los conceptos aquí?

4

El valor al que se establece receiveTimeout indicará al servicio cuánto tiempo esperar antes de fallar el canal de comunicación cuando no se recibe ningún mensaje de aplicación. Siempre puede aumentar este valor de tiempo de espera a un número mayor (el valor predeterminado es de 10 minutos), pero también debe aumentar el tiempo de inactividad de la sesión. Consulte http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.receivetimeout.aspx para obtener más información sobre estos dos tiempos de espera.

Cuando el tiempo de espera de recepción o inactividad se dispara, el canal dúplex presenta una falla. Deberá crear un nuevo proxy en el lado del cliente para poder comunicarse nuevamente con el servidor.

Siempre puede verificar el estado de conexión del canal en el lado del cliente antes de intentar llamar al servidor. Si el CommunicationState del canal no está abierto, entonces puede crear un nuevo proxy antes de llamar al servidor.