IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

C# Socket asynchrone


Sujet :

C#

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Par défaut C# Socket asynchrone
    Bonjour.

    Dans le cadre d'un développement d'une application orienté réseau basé sur les sockets, je me retrouve confronté à un problème assez génant.

    En effet, je travaille avec un moteur basé sur les sockets en mode asynchrone, mais dès que je déconnecte le socket de l'application hote, il m'est impossible de relancer une écoute "proprement".

    Voici ma méthode asynchrone de déconnexion :
    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
      public void Disconnect()
            {
                if (reader.socket != null)
                {
                    if(reader.socket.Connected)
                         reader.socket.BeginDisconnect(true, new AsyncCallback(DisconnectCallBack), reader.socket);
                }
     
            }
     
           private void DisconnectCallBack(IAsyncResult result)
            {
     
                (result.AsyncState as Socket).EndDisconnect(result);
     
                if (Disconnected != null)
                    Disconnected(this, EventArgs.Empty);
     
            }
    et l'endroit où le code plante :

    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
     
     public void WaitConnexion(IPEndPoint localEP)
            {
                if (localEP.Port != XXXX)
                {
                    MessageBox.Show("Le port doit être XXXX");
                    return;
                }
     
                if (reader.socket != null)
                    if (reader.socket.Connected)
                    {
                        MessageBox.Show("Vous êtes déjà connecté", "Conflit de connexion", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                        return;
                    }
     
                LocalEndPoint = localEP;
     
     
                // on bind le socket avec le endpoint local, et on le met en attente de connexion asynchrone
     
                reader.socket.Bind(localEP);  // plantage ici lors d'un bind après le //EndDisconnect, soit pour cause d'argument invalide, soit pour cause de //port déja utilisé
     
                reader.socket.Listen(1);
     
                reader.socket.BeginAccept(new AsyncCallback(WaitConnexionCallBack), reader.socket);
            }

    reader est un objet qui contient le buffer, une constante sur la taille du buffer et le socket utilisé dans l'intégralité du moteur.

    La seule méthode que j'ai trouvé et qui marche correctement est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //ajouté dans le DisconnectCallBack
                    reader.socket.Close();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // ajouté dans le WaitConnexion :
     
    reader.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    Mais passer par le garbage collector pour nettoyer les informations du socket de la mémoire, c'est un peu goret a mon goût et j'aimerais savoir si il n'y a pas une VRAIE méthode pour résoudre ce problème.

    J'ai déjà essayé ceci, sans succès :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     reader.socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)

    En espérant avoir été clair et que quelqu'un pourra m'éclairer ...

    Cordialement,

    KiTe

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Cf. Doc MSDN
    public class Socket : IDisposable

    Donc la classe "Socket" implémente l'interface "IDisposable".
    Il faut donc utiliser la méthode "Dispose" de cette interface pour libérer toutes les ressources non-managées (comme un port TCP) quand on n'a plus besoin de lui.
    le mot clé "using" (ne pas le confondre avec la déclaration de l'utilisation d'un namespace) permet un appel automatique de cette méthode en sortie de scope d'une variable.
    Donc vous n'avez pas besoin d'utiliser le GC comme un goret.

    Je ne vois pas pourquoi vous voulez fermer votre Socket d'écoute (celle qui fait Listen). L'Accept doit générer un nouveau Socket comme socket de travail est laisse le Socket d'écoute libre pour une nouvelle connexion.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Par défaut
    La méthode dispose() n'est plus accessible directement en .NET3.5 malheureusement.

    Et j'utilise toujours le même socket car il n'est pas utile dans maintenir 2 ouverts, dans la mesure ou il ne peut y avoir qu'une connexion unique entre le "serveur" et le client.

    Imagine donc plutôt ça comme un jeu en P2P : il est inutile de laisser un socket en écoute pendant la durée de la partie.

    Je vais essayer de voir si il est possible d'accéder a la propriété dispose convenablement en castant le socket en IDisposable afin d'accèder à Dispose

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 32
    Par défaut
    Finalement je suis reparti sur la solution que tu m'as donné qui marche très bien.

    Voici l'implémentation que j'en ai fais (me corriger si ce n'est pas très bon ^^) :

    - ajout d'un socket WorkingSocket dans la classe reader (l'autre se nomme donc ConnexionSocket).

    - celui qui se connecte utilise d'emblée le working socket, via lequel on fait les échange (send et receive)

    - celui qui attend une connexion le fait sur le ConnexionSocket, puis dans le WaitConnexionCallBack je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      reader.WorkingSocket = ((Socket)result.AsyncState).EndAccept(result);
    // le socket casté via l'AsyncState étant le ConnexionSocket
    puis utilisation du working socket pour send/receive

    - dans disconnect, on déconnecte juste le WorkingSocket dans les deux cas

    - ajout de Dispose dans l'engine pour libérer le ConnexionSocket a la fin du programme

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 15/02/2007, 14h14
  2. [WinAPI][winsock2][visual C++]socket asynchrone
    Par jldgbu dans le forum Windows
    Réponses: 2
    Dernier message: 15/10/2006, 18h34
  3. UDP/TCP multithreading/sockets asynchrones
    Par narkotik dans le forum C++
    Réponses: 4
    Dernier message: 25/07/2006, 11h35
  4. Erreur Socket Asynchrone 10053
    Par QAYS dans le forum Delphi
    Réponses: 2
    Dernier message: 16/06/2006, 07h44
  5. connexion socket asynchrone
    Par jagboys dans le forum C++Builder
    Réponses: 3
    Dernier message: 17/06/2005, 17h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo