web-dev-qa-db-fra.com

WCF NamedPipe CommunicationException - "Le canal a été terminé. (109, 0x6d)."

J'écris un service Windows avec "l'outil d'état". Le service héberge un point de terminaison de canal nommé WCF pour la communication interprocessus. Grâce au canal nommé, l'outil d'état peut périodiquement interroger le service pour obtenir le dernier "état".

enter image description here

Sur ma machine de développement, j'ai plusieurs adresses IP. l'un d'eux est un réseau "local" avec une adresse 192.168.1.XX. L'autre est le réseau "d'entreprise", avec une adresse 10.0.X.XX. Le service Windows collecte le trafic de multidiffusion UDP sur une seule adresse IP.

Jusqu'à présent, le service Windows fonctionnait correctement tant qu'il utilisait l'adresse "192.168.1.XX,". Il enregistre systématiquement le statut correctement au client.

Dès que je suis passé à l'autre adresse IP "entreprise" (10.0.X.XX) et que j'ai redémarré le service, je reçois en permanence des "CommunicationsExceptions" lors de l'extraction du statut:

"There was an error reading from the pipe: The pipe has been ended. (109, 0x6d)."

À présent, je ne pense pas que l'adresse IP "revendiquée" du client UDP devrait avoir quelque chose à voir avec la fonctionnalité de l'interface Named-Pipe; ce sont des pièces complètement séparées de l'application!

Voici les sections pertinentes de la configuration WCF:

//On the Client app:
string myNamedPipe = "net.pipe://127.0.0.1/MyNamedPipe";
ChannelFactory<IMyService> proxyFactory =
    new ChannelFactory<IMyService>(
        new NetNamedPipeBinding(),
        new EndpointAddress(myNamedPipe));


//On the Windows Service:
string myNamedPipe = "net.pipe://127.0.0.1/MyNamedPipe";
myService = new MyService(myCustomArgs);
serviceContractHost = new ServiceHost(myService );
serviceContractHost.AddServiceEndpoint(
    typeof(IMyService),
    new NetNamedPipeBinding(),
    myNamedPipe);

serviceContractHost.Open();

Je ne pense pas qu'il s'agisse d'un problème d'autorisations - j'utilise le client avec des privilèges d'administrateur - mais il y a peut-être une raison spécifique à un domaine qui a provoqué cette défaillance?

14
BTownTKD

Il s’est avéré que l’adresse IP était un véritable fil rouge.

La vraie raison de l'exception était que des valeurs Enum non valides étaient renvoyées par le service WCF.

Mon enum a été défini ainsi:

[DataContract]
public enum MyEnumValues : Byte
{
    [EnumMember]
    Enum1 = 0x10,
    [EnumMember]
    Enum2 = 0x20,
    [EnumMember]
    Enum3 = 0x30,
    [EnumMember]
    Enum4 = 0x40,
} 

Ça a l'air bien en surface.

Mais l'état brut indiqué par le service sous-jacent était une valeur d'octet de "0" et aucune valeur Enum correspondante ne pouvait être exprimée.

Une fois que je me suis assuré que les valeurs Enum étaient toutes valides, l'outil s'est éclairé comme un arbre de Noël.

En cas de doute, supposez que vos données WCF ne sont pas valides.

11
BTownTKD

Cette exception signifie qu'il existe un problème de sérialisation côté serveur. 

Ce problème peut être résolu en consultant le fichier de trace (svclog). Pour activer le traçage, utilisez la configuration suivante:

<system.diagnostics>
        <sources>
            <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="false">
                <listeners>
                    <add name="traceListener" />
                </listeners>
            </source>
            <source name="System.ServiceModel.MessageLogging">
                <listeners>
                    <add name="traceListener" />
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Remos\Log\WcfTraceServer.svclog" />
        </sharedListeners>
    </system.diagnostics>

Dans mon cas, je sérialisais une valeur qui n'était pas dans l'énum.

4
Martin Staufcik

Avait le même problème There was an error reading from the pipe: Unrecognized error 109 (0x6d).

  • Une des raisons était incohérence entre le client et le serveur <netNamedPipeBinding> <security mode="None"></security>... (pas de communication)
  • L'autre problème intermittent était lié au délai d'attente.

Les deux avaient le même message d'erreur en haut.

L'augmentation de time out dans la liaison serveur et client a empêché la réapparition du problème. 

Délai d'attente de liaison défini trop bas:

sendTimeout="00:00:05" receiveTimeout="00:00:05"

Trace de pile: at System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout) at System.ServiceModel.Channels.SessionConnectionReader.Receive(TimeSpan timeout) at System.ServiceModel.Channels.SynchronizedMessageSource.Receive(TimeSpan timeout) at System.ServiceModel.Channels.TransportDuplexSessionChannel.Receive(TimeSpan timeout) at System.ServiceModel.Channels.TransportDuplexSessionChannel.TryReceive(TimeSpan timeout, Message& message) at System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(iMessage message)

3
Wojciech

Parfois, cette erreur est causée par une caractéristique polymorphe des objets. Par exemple, la méthode suivante du service retournera la liste des personnes:

[OperationContract]
 List<Person> GetEmployee();

si nous avons la classe Supervisor héritée de la classe Person et que la méthode ci-dessus essaie de renvoyer Supervisor Object, la classe de sérialiseur WCF ne peut pas interpréter la réponse; cette erreur sera donc générée .
La solution à ce problème consiste à utiliser "types connus" ou "service types connus" . nous devons spécifier que les objets implicites peuvent interagir en utilisant method ou service . Pour mon exemple, nous pouvons mettre l'attribut ServiceKnownType dans la déclaration de la méthode ou du service comme code suivant:

[OperationContract]
[ServiceKnownType(typeof(Supervisor))]
List<Person> GetEmployee();
3
AAAA

Cela s'est produit dans mon service WCF lorsque la charge utile renvoyée était trop importante. Corrigé en ajoutant ceci à un serviceBehavior dans app.config:

<dataContractSerializer maxItemsInObjectGraph="[some big number]" />
2
pizza247

J'avais beaucoup de propriétés sans ensemble {}. Ajouter ceci a résolu mon problème. 

1
Rahbek

J'ai eu cette erreur lorsque l'opération de service a jeté et le canal a été réellement mis en défaut. Dans votre cas, vous avez déjà vérifié que l'opération de service en tant que telle s'est terminée correctement et que seul le retour a été effectué, mais en cas de doute, assurez-vous que l'opération de service fonctionne correctement.

1
J S

J'avais ce problème parce que j'utilisais un ancien tutoriel , et que je tentais de configurer par programme. 

La partie qui me manquait était de fournir le point de terminaison des métadonnées ( merci, cet article! ).

ServiceMetadataBehavior serviceMetadataBehavior = 
    Host.Description.Behaviors.Find<ServiceMetadataBehavior>();

if (serviceMetadataBehavior == null)
{
    serviceMetadataBehavior = new ServiceMetadataBehavior();
    Host.Description.Behaviors.Add(serviceMetadataBehavior);
}

Host.AddServiceEndpoint(
    typeof(IMetadataExchange), 
    MetadataExchangeBindings.CreateMexNamedPipeBinding(), 
    "net.pipe://localhost/PipeReverse/mex"
);
0
Ben

Même problème mais résolu grâce à Wojciech 's answer .

J'ai dû creuser un peu plus pour trouver où placer la balise <security>. Voici comment se présente le début de la section system.serviceModel.

<system.serviceModel>
   <bindings>
     <netNamedPipeBinding>
       <binding>
         <security mode="None"></security>
       </binding>
     </netNamedPipeBinding>
   </bindings>
   ....
0