2010-05-12 4 views
5

J'ai reçu un service WCF hôte/client et un client qui utilise netTcpBinding et une méthode de rappel.WCF, callback duplex, 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

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

instance client avec rappel

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

Le problème que j'ai est que, après la recieveTimeout de liaison déclenche, le client passe dans un état défaillant et ferme les clients d'écoute rappeler.

Je peux voir le port d'écoute tomber en utilisant TCPVIEW de sysinternals.

Si je maintiens le canal occupé, le délai ne se déclenche pas, donc ce n'est pas une erreur dans le message WCF au serveur/client, car plusieurs messages circuleront ok.

Je pensais que le receiveTimeout a été conçu pour fournir un moyen de détecter si une réponse du message WCF sur TCP a échoué? Pourquoi fait-il défaut à la connexion. Il semble presque que s'il n'y a aucun objet de rappel créé pour le délai d'attente, le canal est alors fermé?

Qu'est-ce que je fais mal?

+0

Avez-vous trouvé une solution? –

Répondre

2

Avez-vous essayé d'utiliser un DuplexChannelFactory, dans la création de proxy (client)? Voilà comment il est utilisé (remplacer la création à l'aide nouvelle AlarmServerClient (contexte)):

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

EDIT: L'activation du journal pour analyser la trace:

Il est possible d'analyser la communication des canaux, en permettant l'enregistrement de messages et de trace:

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

Dans ce cas, la trace peut enregistrer "Information". Il est important de voir la création des chaînes.

Pour analyser le fichier svclog, vous pouvez utiliser le Service Trace Viewer - Microsoft Windows SDK, généralement dans C: \ Program Files \ Microsoft SDKs \ Windows \ v6.0A \ bin \ SvcTraceViewer.exe

+0

essayé, n'a pas l'air d'aider. Im toujours baffelled !! – PrimeTSS

+0

Ive a également simplifié les liaisons et débarrassé des temps morts et des propriétés reliablesession encore le canal de rappel va dans un " Etat de la panne (vous aimeriez savoir pourquoi et obtenir plus d'informations sur cette erreur?) – PrimeTSS

+0

En activant le journal, vous pouvez analyser où la communication se bloque. J'espère que cela aide! – Erup

5

Semble la La réception de la réception provoque une défaillance du service d'hôte de rappel après avoir atteint son nombre maximal. Qui est de 23,59 heures ou la valeur par défaut de 1 minute. je peux résoudre le problème de délai d'attente avec la mise à receivetimeout Infinate

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

Mais cela m'a maintenant se demander si im en utilisant vraiment le bon outil dans WFC pour les communications client/serveur. Je souhaite qu'un hôte/serveur s'exécute sur un serveur de fichiers et que plusieurs clients distants y soient connectés. Le client exécutera une commande ping sur le serveur avec une pulsation, et le serveur peut parfois envoyer une commande au client. Je faisais cela avec remoting ou tcpsockets et en utilisant une "méthode d'interrogation client", où les commandes étaient quued dans une base de données et quand le client interrogeait le serveur pour une commande toutes les 10 minutes, s'il y avait une commande en attente pour ce client unique il.Cela a fonctionné correctement, et avait l'avantage de ne pas avoir 1000 connexions de socket tcp ouvertes sur le serveur, car le client se connecterait et se déconnecterait aléatoirement. MAIS j'ai décidé d'essayer WCF (après tout, n'est-ce pas le nouveau dernier en date en remplaçant Remoting?) Et quand j'ai trouvé Duplex je pensais, Id l'utiliser .... Maintenant Im Im penser Im manquant le point sur ce que WCF Duplux est ???

Ai-je manqué les concepts ici ???

4

La valeur à laquelle receiveTimeout est défini indiquera au service combien de temps il doit attendre avant de mettre en défaut le canal de communication lorsqu'aucun message d'application n'est reçu. Vous pouvez toujours augmenter cette valeur de délai d'attente à un nombre supérieur (la valeur par défaut est de 10 minutes), mais vous devez également augmenter le délai d'inactivité de la session. Veuillez consulter le http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.receivetimeout.aspx pour plus d'informations sur ces deux délais.

Lorsque le délai d'attente de réception ou d'inactivité est activé, le canal duplex est en défaut. Vous devrez créer un nouveau proxy côté client pour pouvoir communiquer à nouveau avec le serveur.

Vous pouvez toujours vérifier l'état de la connexion du canal côté client avant d'essayer d'appeler le serveur. Si le CommunicationState du canal n'est pas ouvert, vous pouvez créer un nouveau proxy avant d'appeler le serveur.

Questions connexes