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

Réseau C Discussion :

Serveur multithread et protection par mutex


Sujet :

Réseau C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 4
    Points
    4
    Par défaut Serveur multithread et protection par mutex
    salut ,

    j'ai creer un serveur multithread en ecoute infini.A chaque nouvelle connextion il lance un nouveau thread dédié à un uilisateur :thread_user.
    Voila la variable globale qui me pose probleme.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    //variable globale
    typedef struct info
    {
     
        int socket;
        char IP[15];
        int port;
     
     
    } infos;
    Donc en fait quand un utilisateur se connecte .Le serveur récupere son adresse ip et le port .Elle inscrit ces information avec la nouvelle socket creer dans la variable globale info.
    Elle envoie le tout au thread nouvellement creer et se met immédiatement en reécoute d'une nouvelle connextion.Le thread récupere en local le contenu de la variable globale.
    Le probleme est que si au meme moment un nouveau client se connecte pendant qu'un thread recupere en local les info de la variables,il risque d'y avoir des soucis pour le thread.
    Donc comment protéger avec les mutex une variable globales?
    Merci

    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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    int main()
    {
     
    //mise en place socket
    //début de la boucle infini 
        while(1)
        {
            evenement("attente d'une nouvelle connextion");
            /*acceptation des clients et creation d'une nouvelle socket client */
            socket_client=accept(sock,(struct sockaddr *)&adresse_client,&taille);
     
            /*test d'erreur de la fonction newsock*/
            if(socket_client<0)
            {
                perror("erreur de la fonction accept");
                return 1;
            }
     
    s
            //acceuil d'un nouveau client
     
            /*un nouveau utilisateur viens de se connexter .on collecte ses information
             * de connextion :adresse IP,son port,la nouvelle socket(newsock)*/
            infos info_client;
            pthread_mutex_lock(&mutex);
            strcpy(info_client.IP,inet_ntoa (adresse_client.sin_addr));
            info_client.socket=socket_client;
            info_client.port=ntohs(adresse_client.sin_port);
     
     
     
     
            /*preparation des thread clients*/
            pthread_mutex_unlock(&mutex);
            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
            pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);
            /*lancement des thread proprement dit*/
            if(pthread_create(&threadid,&attr,thread_user,(void *)&info_client)==0)
            {
     
                continue;
            }
            else
            {
                close(socket_client);
            }
        }
     
     
     
      close(sock);
     
        close(socket_client);
     
        return 0;
     
    }
    //une partie du code de thread_user
     
    void* thread_user (void *info_client)
    {
     
        int id_user;
        char media[20];
     
        infos *infoclient=(infos *)info_client;
     
        /*on inscrit en local les information sur  l'utilisateur
         * son adresse ip,la socket de communication,le port */
        infos info_local;
        info_local.socket=infoclient->socket;
        strcpy(info_local.IP,infoclient->IP);
     
     
        info_local.port=infoclient->port;
        //reste  du code

  2. #2
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    une idée possible est de faire un mutex lock/unlock autour de la variable globale
    dans la fonction thread_user et de d'endormir quelque milliseconde la fonction main avant qu'elle ne se remette en reécoute immédiatement.ainsi la fonction thread_user a largement le temps de copier en local le contenu de la variable globale.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Le mieux est de NE PAS utiliser de variable globale du tout, surtout que tu n'es même pas sûr de pouvoir partager des infos de cette façon (voir T.L.S.). L'exemple que tu nous donnes est une des nombreuses raisons pour lesquelles l'usage des globales est proscrit par défaut.

    La temporisation type polling est à bannir également, quand on peut faire autrement. Ça risque de plomber les performances de ton serveur en cas de montée en charge de façon assez dramatique, sans pouvoir garantir de façon certaines ce qui va se passer sur les différentes machines, spécialement si elles sont très rapide ou, au contraire, très lentes.

    Le mieux reste d'allouer une zone de mémoire de la taille de ta structure avant accept(), de remplir cette zone plutôt que la globale, de passer son adresse en argument à ta routine lors de pthread_create() et de laisser cette routine libérer cette mémoire allouée elle-même.

    Si, toutefois, tu tiens à ta globale, ce qu'il faut faire, c'est faire verrouiller le mutex par le serveur, et le faire déverrouiller par la routine cliente. Comme les mutex pthreads ne sont pas trop faits pour cela, tu peux soit utiliser un sémaphore SysV, soit utiliser deux mutex pour synchroniser tes threads, mais gare aux deadlocks.

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    excellent!
    MErci Obsidian,grace a toi j'ai resolu mon probleme de concurence!
    J'ai utilisé la solution du malloc toute simple mais tres efficace.

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

Discussions similaires

  1. Serveur multithreads, envoie données par socket
    Par Orci76 dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 15/07/2010, 18h44
  2. Arrêt d'un serveur multithread
    Par bambou dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 07/07/2010, 17h04
  3. Protection par blocage de répertoire?
    Par Madmac dans le forum Windows XP
    Réponses: 15
    Dernier message: 09/02/2006, 01h41
  4. Réponses: 5
    Dernier message: 11/01/2006, 08h58

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