Partage
  • Partager sur Facebook
  • Partager sur Twitter

Socket Client/Server Asynchrone

Sujet résolu
    15 décembre 2020 à 1:03:10

    Bonjour,

    J'utilise le client/server en application de message reçu du client, faire mes affaires et renvoyer au message client.

    J'ai utilisé les exemples de la doc Microsoft pour faire client/server asynchrone:

    http://msdn.microsoft.com/en-us/library/bew39x2a.aspx

    http://msdn.microsoft.com/en-us/library/fx6588te.aspx

    Quand j'envoie juste un message du serveur vers le client, cela fonctionne.

    Mais si je veux faire une boucle, ou j'envoie plusieurs informations à la suite du serveur vers le client, cela ne fonctionne pas. Je reçois cela comme message d'erreur : Cannot access a disposed object

    Sur la fonction : 

    handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);

    Je ne comrpend vraiment pas trop cette erreur, je voulais savoir si quelqu'un avait deja reussi à la patcher ? Merci d'avance.

    • Partager sur Facebook
    • Partager sur Twitter
      15 décembre 2020 à 10:38:08

      Il nous manque un peu de code.

      Vraisemblablement, vous utilisez un objet à usage unique.

      -
      Edité par bacelar 15 décembre 2020 à 11:12:10

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        15 décembre 2020 à 10:55:46

        Voici mon serveur : 

        J'appelle la fonction StartServer, dans un thread quand le programme se lance.

         public static ManualResetEvent allDone = new ManualResetEvent(false); 
        public void StartServer()
                {
        
                    // Establish the local endpoint for the socket.    
                    IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
                    IPAddress ipAddress = ipHostInfo.AddressList[0];
                    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 8080);
        
                    // Create a TCP/IP socket.  
                    Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        
                    // Bind the socket to the local endpoint and listen for incoming connections.  
                    try
                    {
                        listener.Bind(localEndPoint);
                        listener.Listen(100);
        
                        while (true)
                        {
                            // Set the event to nonsignaled state.  
                            allDone.Reset();
        
                            // Start an asynchronous socket to listen for connections. 
                            MessageBox.Show("Waiting for a connection...");
                            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        
                            // Wait until a connection is made before continuing.  
                            allDone.WaitOne();
                        }
        
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.ToString());
                    }
                }
        
                public void AcceptCallback(IAsyncResult ar)
                {
                    // Signal the main thread to continue.  
                    allDone.Set();
        
                    // Get the socket that handles the client request.  
                    Socket listener = (Socket)ar.AsyncState;
                    Socket handler = listener.EndAccept(ar);
        
                    // Create the state object.  
                    StateObject state = new StateObject();
                    state.workSocket = handler;
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                }
        
                public void ReadCallback(IAsyncResult ar)
                {
                    String content = String.Empty;
        
                    // Retrieve the state object and the handler socket  
                    // from the asynchronous state object.  
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket handler = state.workSocket;
        
                    // Read data from the client socket.
                    int bytesRead = handler.EndReceive(ar);
        
                    if (bytesRead >= 0)
                    {
                        // There  might be more data, so store the data received so far.  
                        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
        
        
                        // Check for end-of-file tag. If it is not there, read
                        // more data.  
                        content = state.sb.ToString();
                        if (content.IndexOf("getdata") > -1)
                        {
                            // Send(handler, "Test" + Environment.NewLine);
                            // All the data has been read from the
                            // client. Display it on the console.
                            // Echo the data back to the client.  
                            List<string> names = viewmodel.ListBackup();
                            foreach (var name in names)//Loop that allows you to manage the names in the list.
                            {
              
                                Send(handler, name + Environment.NewLine); //Function that allows you to insert the names of the backups in the list.
                                                                           // MessageBox.Show(name);
                            }
                
        
                        }
                        else
                        {
                            // Not all data received. Get more.  
                            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                        }
                    }
                }
        
                private void Send(Socket handler, String data)
                {
                    try
                    {
                        // Convert the string data to byte data using ASCII encoding.  
                        byte[] byteData = Encoding.ASCII.GetBytes(data);
        
                        // Begin sending the data to the remote device.  
                        handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
        
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.ToString());
                    }
        
                }
        
        
                private void SendCallback(IAsyncResult ar)
                {
                    Socket handler = (Socket)ar.AsyncState;
                    try
                    {
                        // Retrieve the socket from the state object.  
        
        
                        // Complete sending the data to the remote device.  
                        int bytesSent = handler.EndSend(ar);
                        //MessageBox.Show("Sent {0} bytes to client." + bytesSent);
        
                        handler.Shutdown(SocketShutdown.Both);
                        handler.Close();
        
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.ToString());
                    }
                }

        Et voici l'erreur de la fenetre dans mon try catch:

        Je reçois bien la 1er valeur mais quand il refait la boucle et bien c'est ici que j'ai l'erreur.

        -
        Edité par Monocop 15 décembre 2020 à 11:00:11

        • Partager sur Facebook
        • Partager sur Twitter
          15 décembre 2020 à 11:07:46

          Monocop a écrit:

          Voici mon serveur : 

          J'appelle la fonction StartServer, dans un thread quand le programme se lance.

           public static ManualResetEvent allDone = new ManualResetEvent(false); 
          public void StartServer()
                  {
          
                      // Establish the local endpoint for the socket.    
                      IPHostEntry ipHostInfo = Dns.GetHostEntry("localhost");
                      IPAddress ipAddress = ipHostInfo.AddressList[0];
                      IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 8080);
          
                      // Create a TCP/IP socket.  
                      Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
          
                      // Bind the socket to the local endpoint and listen for incoming connections.  
                      try
                      {
                          listener.Bind(localEndPoint);
                          listener.Listen(100);
          
                          while (true)
                          {
                              // Set the event to nonsignaled state.  
                              allDone.Reset();
          
                              // Start an asynchronous socket to listen for connections. 
                              MessageBox.Show("Waiting for a connection...");
                              listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
          
                              // Wait until a connection is made before continuing.  
                              allDone.WaitOne();
                          }
          
                      }
                      catch (Exception e)
                      {
                          MessageBox.Show(e.ToString());
                      }
                  }
          
                  public void AcceptCallback(IAsyncResult ar)
                  {
                      // Signal the main thread to continue.  
                      allDone.Set();
          
                      // Get the socket that handles the client request.  
                      Socket listener = (Socket)ar.AsyncState;
                      Socket handler = listener.EndAccept(ar);
          
                      // Create the state object.  
                      StateObject state = new StateObject();
                      state.workSocket = handler;
                      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                  }
          
                  public void ReadCallback(IAsyncResult ar)
                  {
                      String content = String.Empty;
          
                      // Retrieve the state object and the handler socket  
                      // from the asynchronous state object.  
                      StateObject state = (StateObject)ar.AsyncState;
                      Socket handler = state.workSocket;
          
                      // Read data from the client socket.
                      int bytesRead = handler.EndReceive(ar);
          
                      if (bytesRead >= 0)
                      {
                          // There  might be more data, so store the data received so far.  
                          state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
          
          
                          // Check for end-of-file tag. If it is not there, read
                          // more data.  
                          content = state.sb.ToString();
                          if (content.IndexOf("getdata") > -1)
                          {
                              // Send(handler, "Test" + Environment.NewLine);
                              // All the data has been read from the
                              // client. Display it on the console.
                              // Echo the data back to the client.  
                              List<string> names = viewmodel.ListBackup();
                              foreach (var name in names)//Loop that allows you to manage the names in the list.
                              {
                
                                  Send(handler, name + Environment.NewLine); //Function that allows you to insert the names of the backups in the list.
                                                                             // MessageBox.Show(name);
                              }
                  
          
                          }
                          else
                          {
                              // Not all data received. Get more.  
                              handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                          }
                      }
                  }
          
                  private void Send(Socket handler, String data)
                  {
                      try
                      {
                          // Convert the string data to byte data using ASCII encoding.  
                          byte[] byteData = Encoding.ASCII.GetBytes(data);
          
                          // Begin sending the data to the remote device.  
                          handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
          
                      }
                      catch (Exception e)
                      {
                          MessageBox.Show(e.ToString());
                      }
          
                  }
          
          
                  private void SendCallback(IAsyncResult ar)
                  {
                      Socket handler = (Socket)ar.AsyncState;
                      try
                      {
                          // Retrieve the socket from the state object.  
          
          
                          // Complete sending the data to the remote device.  
                          int bytesSent = handler.EndSend(ar);
                          //MessageBox.Show("Sent {0} bytes to client." + bytesSent);
          
                          handler.Shutdown(SocketShutdown.Both);
                          handler.Close();
          
                      }
                      catch (Exception e)
                      {
                          MessageBox.Show(e.ToString());
                      }
                  }

          Et voici l'erreur de la fenetre dans mon try catch:

          Je reçois bien la 1er valeur mais quand il refait la boucle et bien c'est ici que j'ai l'erreur.

          -
          Edité par Monocop il y a moins de 30s

          handler.Shutdown(SocketShutdown.Both);
          handler.Close();
          Supprimez ces lignes


          • Partager sur Facebook
          • Partager sur Twitter
            15 décembre 2020 à 11:13:09

            XTZ95 a écrit:

            handler.Shutdown(SocketShutdown.Both);
            handler.Close();

            Supprimez ces lignes


            Je viens de le faire, je ne reçois plus rien. Mais au dessus de ce que j'ai supprimé, j'ai mis le Messsage.Box. Voici le resultat, cela affiche bien le nombre dans la boucle dans les message box: 

            -
            Edité par Monocop 15 décembre 2020 à 11:20:32

            • Partager sur Facebook
            • Partager sur Twitter
              15 décembre 2020 à 11:35:15

              C'est du Client/Server à la HTTP sans Keep-Alive. Le serveur répond à la requête et ferme la socket.

              C'est donc une socket "accepté" à usage unique.

              Si vous voulez un autre mécanisme, il faut reprendre assez profondément vos exemples.

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                15 décembre 2020 à 11:39:02

                Je comprends, mais j'ai un ami qui a le même code que moi, et lui cela fonctionne parfaitement.

                C'est pour ça que je ne comprends pas du tout.

                J'ai testé son serveur avec mon client, je reçois bien les informations comme je veux.

                Est-ce que ce serait pas le .net Core 3.1 qui me ferait défaut.

                Car je viens d'apprendre que mon amis est en .net Framework

                -
                Edité par Monocop 15 décembre 2020 à 12:37:14

                • Partager sur Facebook
                • Partager sur Twitter
                  15 décembre 2020 à 13:24:13

                  Monocop a écrit:

                  Je comprends, mais j'ai un ami qui a le même code que moi, et lui cela fonctionne parfaitement.

                  C'est pour ça que je ne comprends pas du tout.

                  J'ai testé son serveur avec mon client, je reçois bien les informations comme je veux.

                  Est-ce que ce serait pas le .net Core 3.1 qui me ferait défaut.

                  Car je viens d'apprendre que mon amis est en .net Framework

                  -
                  Edité par Monocop il y a 44 minutes

                  handler.Close();
                  En supprimant juste cette ligne normalement, votre objet ne va pas se disposer.
                  L'autre ligne au dessus semble terminer la communication. Peut-être qu'en .net framework la fonction .Close(); ne dispose pas l'objet.


                  • Partager sur Facebook
                  • Partager sur Twitter
                    15 décembre 2020 à 13:46:56

                    Je viens d'essayer en supprimant la ligne que vous m'avez dit. Voici le message d'erreur qui est différent: 

                    Mais je pense vraiment que le probleme vient du .Net Core 3.1, mais aucune information sur le doc de Microsoft

                    -
                    Edité par Monocop 15 décembre 2020 à 13:47:08

                    • Partager sur Facebook
                    • Partager sur Twitter
                      15 décembre 2020 à 15:04:35

                      >probleme vient du .Net Core 3.1,

                      Ou c'est plutôt grâce à lui que vous détectez un bug qui reste latent chez votre ami.

                      Le "Close", c'est lié au garbage-collector, et il n'est pas déterministe.

                      Si vous fermez la socket ("Shutdown(SocketShutdown.Both)"), pourquoi ne voulez-vous pas que le garbage-collector fasse son travail ???

                      Soit vous laissez les 2 et vous gérez vos communication à la HTTP 1.0, soit vous n'en laisser aucune.

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        15 décembre 2020 à 15:16:40

                        bacelar a écrit:

                        >probleme vient du .Net Core 3.1,

                        Ou c'est plutôt grâce à lui que vous détectez un bug qui reste latent chez votre ami.

                        Le "Close", c'est lié au garbage-collector, et il n'est pas déterministe.

                        Si vous fermez la socket ("Shutdown(SocketShutdown.Both)"), pourquoi ne voulez-vous pas que le garbage-collector fasse son travail ???

                        Soit vous laissez les 2 et vous gérez vos communication à la HTTP 1.0, soit vous n'en laisser aucune.

                        J'ai enlevé les deux dans le client et serveur. Sauf que maintenant, je ne reçois plus rien.

                        Alors que si je laisse les deux, je reçois la 1er information de ma liste.

                        EDIT: Merci, je viens de resoudre le problemes:

                        private void ReadCallback(IAsyncResult ar)
                                    {
                                        String content = String.Empty;
                        
                                        try
                                        {
                                            StateObject state = (StateObject)ar.AsyncState;
                                            Socket handler = state.workSocket;
                        
                                            int byteRead = handler.EndReceive(ar);
                        
                                            if (byteRead > 0)
                                            {
                                                state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, byteRead));
                                                content = state.sb.ToString();
                                                if (content.IndexOf("getdata") != -1)
                                                {
                                                    List<string> names = viewmodel.ListBackup();
                                                    foreach (var name in names)//Loop that allows you to manage the names in the list.
                                                    {
                                                        Send(handler, name + Environment.NewLine); //Function that allows you to insert the names of the backups in the list.
                                                    }
                        
                                                }
                                                else
                                                {
                                                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                                                }
                        
                                                handler.Shutdown(SocketShutdown.Both);
                                                handler.Close(100);
                                            }
                                        }catch
                                            {
                        
                                            }
                                            
                                    }


                        J'ai donc déplacer le : 

                                                handler.Shutdown(SocketShutdown.Both);
                        handler.Close(100);

                        Dans le try catch du readCallBack.

                        Merci en tout cas, je vous remercie.



                        -
                        Edité par Monocop 15 décembre 2020 à 15:27:14

                        • Partager sur Facebook
                        • Partager sur Twitter
                          15 décembre 2020 à 16:36:45

                          Vous n'avez donc absolument pas compris comment fonctionne le protocole TCP/IP et en particulier son démarrage lent et la purge des flux.

                          Si vous ne maîtrisez pas un minimum TCP, utilisez UDP qui est plus intuitif et orienté message, lui.

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                          Socket Client/Server Asynchrone

                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                          • Editeur
                          • Markdown