Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 7 sur 7
  1. #1
    Invité régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    août 2011
    Messages
    21
    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 : 21
    Points : 8
    Points
    8

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

  2. #2
    Inactif
    Homme Profil pro François
    Chef de projet NTIC
    Inscrit en
    janvier 2007
    Messages
    6 608
    Détails du profil
    Informations personnelles :
    Nom : Homme François
    Âge : 53
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : janvier 2007
    Messages : 6 608
    Points : 12 114
    Points
    12 114

    Par défaut

    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.

  3. #3
    Rédacteur/Modérateur



    Homme Profil pro Thomas Levesque
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 209
    Détails du profil
    Informations personnelles :
    Nom : Homme Thomas Levesque
    Âge : 33
    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 : 19 209
    Points : 36 702
    Points
    36 702

    Par défaut

    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)

  4. #4
    Invité régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    août 2011
    Messages
    21
    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 : 21
    Points : 8
    Points
    8

    Par défaut

    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

  5. #5
    Invité régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    août 2011
    Messages
    21
    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 : 21
    Points : 8
    Points
    8

    Par défaut

    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().

  6. #6
    Rédacteur/Modérateur



    Homme Profil pro Thomas Levesque
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 209
    Détails du profil
    Informations personnelles :
    Nom : Homme Thomas Levesque
    Âge : 33
    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 : 19 209
    Points : 36 702
    Points
    36 702

    Par défaut

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

  7. #7
    Invité régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    août 2011
    Messages
    21
    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 : 21
    Points : 8
    Points
    8

    Par défaut

    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

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •