Bonjour à tous,
Cela fait un certain temps que je m'arrache les cheveux sur le paramétrage de mon service WCF aussi j'espère que vous pourrez m'aider à trouver une solution.
J'ai mis en place un service WCF, entre un client et un serveur. Ce service est codé de la façon suivante :
Chaque méthode disponible est taggée avec les bons attributs et tout fonctionne correctement (le client et le serveur communiquent bien, mes données sont bien envoyées/reçues), bref tout irait bien si je n'avais pas de problème avec la durée de vie de ma session !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 // Contrat : [ServiceContract(Namespace = "http://www.monservice.com/IT/WCF", SessionMode = SessionMode.Required)] public interface IServiceContract { ... } // Service [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerSession)] public class MonService : IServiceContract, IDisposable { ... }
Voici les configurations de mon client et de mon serveur :
Le problème est donc le suivant : mon application cliente doit pouvoir rester ouverte un certain temps (plusieurs jours d'affilée) sans que la session au serveur ne soit coupée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 // Web.config serveur <system.serviceModel> <services> <service name="MonService " behaviorConfiguration="metadataAndDebugEnabled"> <endpoint address="net.tcp://localhost/WCF.svc" binding="netTcpBinding" bindingConfiguration="MonBinding" contract="IServiceContract" /> <endpoint address="http://localhost:9000/WCF.svc" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <netTcpBinding> <binding name="MonBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="Infinite" sendTimeout="00:15:30" transferMode="Buffered" maxReceivedMessageSize="100000000" maxBufferSize="100000000" maxBufferPoolSize="65536" hostNameComparisonMode="StrongWildcard"> <reliableSession ordered="true" inactivityTimeout="00:00:30" enabled="true" /> <security mode="TransportWithMessageCredential"> <message clientCredentialType="UserName" /> </security> </binding> </netTcpBinding> <mexHttpBinding> <binding name="mexHttpBinding" closeTimeout="24:00:00" openTimeout="24:00:00" receiveTimeout="24:00:00" sendTimeout="24:00:00" /> </mexHttpBinding> </bindings> </system.serviceModel> // App.config client <system.serviceModel> <bindings> <netTcpBinding> <binding name="WS_netTcp" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="Infinite" sendTimeout="00:10:00" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxConnections="10" transferMode="Buffered" maxReceivedMessageSize="100000000"> <readerQuotas maxDepth="100000000" maxStringContentLength="8192" maxArrayLength="65536" maxBytesPerRead="65536" maxNameTableCharCount="65536"/> <reliableSession ordered="true" inactivityTimeout="00:00:10" enabled="true"/> <security mode="TransportWithMessageCredential"> <message clientCredentialType="UserName"/> </security> </binding> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://192.168.0.1/WCF.svc" binding="netTcpBinding" bindingConfiguration="WS_netTcp" contract="IServiceContract" name="MaConfig" behaviorConfiguration="ClientCertificateBehavior"/> </client> </system.serviceModel>
- J'ai donc besoin que ma session ait une durée de vie "infinie", les utilisateurs la laissant tourner généralement toute la semaine...
- Certains utilisateurs font tourner l'application sur des ordinateurs portables. Il arrive fréquemment que, lorsque l'application est ouverte, ils se déconnectent du réseau pour pouvoir se déplacer. J'ai donc besoin de pouvoir détecter les coupures de session pour agir en conséquence sur le client (afficher un message, proposer le reconnexion et désactiver sur l'IHM les opérations nécessitants d'être connecté). J'utilise pour se faire l'événement Faulted du service.
Pour répondre à ces besoins, j'ai tout d'abord mis le paramètre ReceiveTimeOut à "Infinite" afin de signifier à WCF que ma session n'expire jamais et le paramètre l'inactivityTimeOut de reliableSession à "Infinite" également. Il semblerait que ce système fonctionne, ma session ne semblant pas expirer (je n'ai pas pour l'instant eu le temps de faire des tests sur des durées > 1h). Par contre, mettre inactivityTimeOut à "Infinite" entraine le fait que le channel de mon service ne passe jamais dans l'état Faulted, même en cas de déconnexion physique de l'ordinateur faisant tourner mon application. Et passer InactivityTimeOut à une valeur plus basse (30s dans le cas présenté ici) fait que les déconnexion physiques sont bien prises en compte mais ma session s'auto-coupe rapidement dès qu'il n'y a plus d'activité sur le WebService.
Après différentes recherches sur le net, je suis tombé sur des réponses contradictoires : certains sites disent que ma solution est la bonne (et pourtant, ça ne fonctionne pas), d'autres disent qu'il faut mettre en place un démon exécutant régulièrement des appels bidons sur le serveur afin de maintenir la session en vie (ce qui m'embête assez, je ne voudrais pas saturer mon serveur...).
La doc MSDN quant à elle explique que receiveTimeOut est la durée pendant laquelle aucun message de l'application peut ne pas circuler sur le channel sans déclencher d'erreur tandis qu'inactivitytimeOut est la durée pendant laquelle aucun message des couches transport peut ne pas circuler sur le channel sans déclencher d'erreur. A la lumière de ces paramètres, ma configuration me semble donc bonne et je ne comprends pas pourqoi cela ne fonctionne pas !
Bref, j'avoue être perdu. Si quelqu'un à une idée, je suis preneur !
Merci beaucoup par avance,
Hatman
PS : je suis en Framework 4.0
Partager