Précédent   Forum du club des développeurs et IT Pro > Dotnet > Développement Windows > Services Windows
Services Windows Forum d'entraide sur le développement de services Windows.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 25/08/2011, 17h02   #1
Devko
Invité régulier
 
Homme
Développeur .NET
Inscription : août 2011
Messages : 12
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Seine Saint Denis (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2011
Messages : 12
Points : 5
Points : 5
Par défaut Service windows et serveur tcp

Bonjour,

J'ai développé un serveur TCP qui fonctionne parfaitement lorsqu'il est appelé depuis un projet winform. Le but est que ce serveur TCP soit utilisé par un service windows. J'ai intégré ce serveur dans un projet de type DLL, DLL que j'utilise par la suite dans mon projet de service windows... Tout fonctionne parfaitement sauf que... quand je démarre mon service (installé au préalable par installutil monservice) depuis le gestionnaire de service la barre de progression du lancement du service est très lente et me renvoie un
Citation:
erreur 1053 : le service n'a pas répondu assez vite à la demande de lancement ou de controle.
Cela dit étrangement tout fonctionne parfaitement par la suite, le service est bien démarré et le serveur TCP fonctionne(les trames provenant du réseau apparaissent dans le log), seul problème je ne peux plus arrêter mon service depuis le gestionnaire de service car toutes les taches sont grisées de plus le lancement de celui-ci a été très long et c'est soldé par cette erreur 1053...

Merci d'avance pour votre aide.

Le service windows :
Code :
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
 
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;
 
namespace MonService
{
    class Program : ServiceBase
    {
        public Program()
        {
            this.ServiceName = "MonService";
 
        }
 
        static void Main(string[] args)
        {
            ServiceBase.Run(new Program());            
        }
 
        protected override void OnStart(string[] args)
        {
            //Appel de StartListening() : lancement du serveur TCP
            MySocketListener.SocketListener.StartListening();
        }
 
        protected override void OnStop()
        {
            base.OnStop();
        }
    }
}
Le serveur TCP :
Code :
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
 
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Configuration;
using MyTools;
using log4net;
 
namespace MySocketListener
{
    public static class SocketListener
    {
        static String content=string.Empty;
 
        private static readonly ILog log = LogManager.GetLogger(typeof(SocketListener)); 
 
        public static ManualResetEvent allDone = new ManualResetEvent(false);
 
        public static void StartListening()
        {
            byte[] bytes = new Byte[1024];
            IPAddress ipAddress = IPAddress.Parse(ConfigurationManager.AppSettings["networkIFCIP"]); // ipHostInfo.AddressList[1];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Int32.Parse(ConfigurationManager.AppSettings["tcpPort"]));
 
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(100);
 
                while (true)
                {
                    allDone.Reset();
 
                    Console.WriteLine("Waiting for a connection...");
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener); 
                    allDone.WaitOne();
                }
 
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
 
            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }
 
        public static void AcceptCallback(IAsyncResult ar)
        {
            allDone.Set();
 
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
 
            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
        }
 
        public static void ReadCallback(IAsyncResult ar)
        {
            content = String.Empty;
 
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;
 
            int bytesRead = handler.EndReceive(ar);
 
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.GetEncoding("ISO-8859-1").GetString(
                    state.buffer, 0, bytesRead));
                content = state.sb.ToString();
 
 
                    Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
                        content.Length, content);
                    Send(handler, content);
                    log.Debug("Received : " + Tools.GetCtrlCharFormat(content));
 
            }
        }
 
        private static void Send(Socket handler, String data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), handler);
        }
 
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
 
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);
                log.Debug("Sent     : " + Tools.GetCtrlCharFormat(content));
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
 
 
        public static int Main(String[] args)
        {
            log.Debug("Lancement de l'application");
            StartListening();
            log.Debug("Arrêt de l'application");
            return 0;
        }
    }
}
Devko est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/08/2011, 18h11   #2
Bluedeep
Expert Confirmé Sénior
 
Homme François
Chef de projet NTIC
Inscription : janvier 2007
Messages : 6 558
Détails du profil
Informations personnelles :
Nom : Homme François
Âge : 52
Localisation : France

Informations professionnelles :
Activité : Chef de projet NTIC

Informations forums :
Inscription : janvier 2007
Messages : 6 558
Points : 13 958
Points : 13 958
C'est pas étonnnant : ton "Start" n'est pas un start mais une boucle d'exécution qui ne termine jamais.

La méthode OnStart doit démarrer ton service et retourner au SCM pour signaler que le service a démarré sans erreur.

Or, elle ne retourne jamais, donc le SCM en conclue (à juste titre) que ton service n'a pas répondu et pas démarré correctement.

Je te suggère que tu lises un tuto sur la programmation de service en .Net car c'est la c'est une application que tu as écrit, pas un service.
__________________

Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


Une réponse vous a aidé ? utiliser le bouton

"L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel
Bluedeep est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/08/2011, 20h42   #3
tomlev
Rédacteur/Modérateur


 
Avatar de tomlev
 
Homme Thomas Levesque
Développeur .NET
Inscription : février 2004
Messages : 17 839
Détails du profil
Informations personnelles :
Nom : Homme Thomas Levesque
Âge : 31
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2004
Messages : 17 839
Points : 34 229
Points : 34 229
Pour faire simple, la solution est de lancer un nouveau thread qui exécute ta méthode StartListening :

Code :
1
2
3
4
5
6
7
        private Thread _thread;
 
        protected override void OnStart(string[] args)
        {
            _thread = new Thread(MySocketListener.SocketListener.StartListening);
            _thread.Start();
        }
Et pour arrêter le service, tu fais un truc comme ça :

Code :
1
2
3
4
5
6
        protected override void OnStop()
        {
            base.OnStop();
            MySocketListener.SocketListener.StopRequested = true;
            _thread.Join();
        }
(StopRequested étant une propriété de ta classe SocketListener, que ta boucle principale vérifie à chaque itération)
__________________

Pas de questions techniques par MP ! Le forum est là pour ça...

Tutoriels : Les markup extensions en WPF - La sérialisation XML avec .NET (Aller plus loin) - Extraction de données de pages web à l'aide de HTML Agility Pack
Projet : Dvp.NET, la librairie .NET open-source des membres de Developpez !
tomlev est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/08/2011, 11h51   #4
Devko
Invité régulier
 
Homme
Développeur .NET
Inscription : août 2011
Messages : 12
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Seine Saint Denis (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2011
Messages : 12
Points : 5
Points : 5
Tout d'abord merci à vous deux pour vos réponses.

Citation:
Envoyé par Bluedeep Voir le message
Je te suggère que tu lises un tuto sur la programmation de service en .Net car c'est la c'est une application que tu as écrit, pas un service.
Je suppose que tu dis ça par rapport a la méthode public static int Main(String[] args) et aux Console.Writeline ? Au départ j'avais écris ce code dans une application et j'ai juste fait un copier/coller de celui-ci et n'ai pas encore fait le ménage notamment concernant certains éléments devenus inutile. J'aurais effectivement du le faire avant de poster mes extraits de code

Citation:
Envoyé par tomlev
Et pour arrêter le service, tu fais un truc comme ça :
Code :
1
2
3
4
5
6
7
 
 protected override void OnStop()
        {
            base.OnStop();
            MySocketListener.SocketListener.StopRequested = true;
            _thread.Join();
        }
Ta solution fonctionne parfaitement pour le démarrage, je n'ai plus d'erreurs. Par contre pour l'arrêt le service ne s'arrête correctement que si j'envoie un message tcp à mon serveur pendant que je suis en train d'arrêter mon service. Sinon j'ai toujours l'erreur 1053.

J'ai bien créé la propriété StopRequested et ai remplacé ma boucle while(true) par while(!stopRequested). A dire la vérité je ne comprends pas pourquoi ça ne fonctionne pas car dans la logique ça me semble correct... la méthode StartListening est appelé lors du démarrage du service et la propriété StopRequested est testée à chaque itération donc il devrait sortir de la boucle lorsque StopRequested est modifié de false vers true lors du onStop()...

Je ne sais pas si cela est une bonne façon de faire mais l'arrêt du service fonctionne correctement si je supprime ces deux lignes :
Code :
1
2
3
 
MFFSocketListener.SocketListener.StopRequested = true;
_thread.Join();
Qu'en pensez-vous ?


merci
Devko est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/08/2011, 12h15   #5
Devko
Invité régulier
 
Homme
Développeur .NET
Inscription : août 2011
Messages : 12
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Seine Saint Denis (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2011
Messages : 12
Points : 5
Points : 5
J'ai vérifié en mode debug, lors de l'arrêt du service la méthode OnStop() est bien appelée et StopRequested passe bien à true mais le service me renvoie l'erreur 1053 sur le _thread.Join().
Devko est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/08/2011, 14h27   #6
tomlev
Rédacteur/Modérateur


 
Avatar de tomlev
 
Homme Thomas Levesque
Développeur .NET
Inscription : février 2004
Messages : 17 839
Détails du profil
Informations personnelles :
Nom : Homme Thomas Levesque
Âge : 31
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2004
Messages : 17 839
Points : 34 229
Points : 34 229
En fait le problème est dans ta boucle :

Code :
1
2
3
4
5
6
7
8
9
10
                while (!StopRequested)
                {
                    allDone.Reset();
 
                    Console.WriteLine("Waiting for a connection...");
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener); 
                    allDone.WaitOne();
                }
Tu appelles la version asynchrone de Accept (ce qui est bien), mais vu que juste derrière tu appelles allDone.WaitOne(), ça bloque à nouveau, et la condition du while n'est pas retestée avant qu'un client se connecte.

En fait il faudrait que tu mettes un timeout sur le waitone, et que tu boucles jusqu'à ce qu'il renvoie true :

Code :
1
2
3
4
5
6
7
8
9
10
                while (!StopRequested)
                {
                    allDone.Reset();
 
                    Console.WriteLine("Waiting for a connection...");
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener);
                    while (!StopRequested && !allDone.WaitOne(100));
                }
__________________

Pas de questions techniques par MP ! Le forum est là pour ça...

Tutoriels : Les markup extensions en WPF - La sérialisation XML avec .NET (Aller plus loin) - Extraction de données de pages web à l'aide de HTML Agility Pack
Projet : Dvp.NET, la librairie .NET open-source des membres de Developpez !
tomlev est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/08/2011, 15h03   #7
Devko
Invité régulier
 
Homme
Développeur .NET
Inscription : août 2011
Messages : 12
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Seine Saint Denis (Île de France)

Informations professionnelles :
Activité : Développeur .NET
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2011
Messages : 12
Points : 5
Points : 5
Ca parait logique (si j'ai bien tout compris...), il attends une réponse sur le WaitOne pendant 100ms, s'il n'en reçois pas pendant ce laps de temps il se mange le timeout et boucle dans le while imbriqué, StopRequested a été mis à true dans le onstop() et est retesté par la condition de ce while imbriqué donc sortie de la boucle imbriqué puis retest de StopRequest dans le while "parent" et sortie de cette boucle également.

Parfait ! ça fonctionne à merveille ! merci encore
Devko est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 05h41.


 
 
 
 
Partenaires

Hébergement Web