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 :

conception serveur multithread


Sujet :

Réseau C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2006
    Messages : 52
    Par défaut conception serveur multithread
    Bonjour,

    Je sais qu il y a eu pas mal de topic dessus. Mais je donner les information sur mon implementation et avoir vos opinions.

    J ai un server qui est connecte sur un seul port, et j aimerai qu il dialogue avec plusieurs clients.

    Au depart je penser creer un thread pour chaque client et ensuite le detruire. Mais cela risque d etre couteux a chaque fois de creer un thread et de le detruire surtout si le nombre de client est grand.

    J ai donc opte pour le la creation de X threads, et si ces X threads sont tous occupe, alors on attend la terminaison de l un.

    Pour gerer cela, je creer une file qui sera rempli par la main et les thread (de maniere exclusive) prendrons un element de la pile.


    Pour la reception des messages :
    ca serai le main qui s occuperait de receptionner le message et lancerai un thread pour avec les donnees a traiter.

    Pour l envoie des messages :
    Je pense que la meilleure chose a faire et que se soit les thread qui envoie les message aux clients.

    Evidement je devrais utiliser un mutex pour pouvoir lire et ecrire.
    Mais une chose me tracasse, j ai peur le le main recois trop de message et ne laisse pas assez le tps au thread d envoyer les donnees. Dans ce cas la taille du buffer de la socket risque d etre depassee. Pour cela il suffirait peut etre de faire un sleep de 1 seconde (apres que le main ait relache le mutex) pour laisser au thread le temps d envoyer les donner). Mais j ai peur aussi de faire un sleep trop long ce qui exposera la taille du buffer de la socket.
    D ailleurs la taille maximum du buffer d une socket est de combien ?

    Ensuite je dois gerer le cas des sockets bloquantes. pour cela j utilise la fonction select(), ce qui me permettra de gerer les time out (je ne vois que ca pour son utilisation, si y en a dautre n hesitez pas a me le dire).

    voila comment je compte faire.

    Merci de me faire parvenir vos opinions.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 86
    Par défaut
    salut,

    tu te compliques un peu la vie, car le systeme peut gerer beaucoup de choses pour toi, mais tu as raison concernant le "pool" de threads (par opposition a creer un thread a chaque connexion).

    la plupart des serveurs TCP necessitant un temps de latence minimal a la connexion utilisent cette methode; il s'agit du modele "pre-fork" (mis en oeuvre, entre autres, par Apache).

    le principe consiste a creer un certain nombre (configurable) de processus fils en prevision de variations subites du nombre de clients (et donc de connexions); cette technique peut egalement s'adapter aux threads, voire a une combinaison de processus et de threads.

    c'est la que le systeme intervient de facon interessante: lorsque tu crees un socket, et que tu le met en ecoute sur un port, plusieurs threads peuvent simultanement faire un accept() sur ce meme socket. quand une connexion intervient, l'OS l'attribue a un des threads en attente, et le fait sortir du accept(); les autres threads restent en wait.

    je te propose un petit exemple ici.

    il s'agit d'un serveur "echo" (il renvoie a chaque client tout ce qu'il recoit de chacun d'eux). compile-le et lance le avec:

    par defaut, 32 threads sont crees (il peut etre interessant d'en modifier le nombre afin d'observer le comportement du serveur en cas de nombreuses connexions). tu peux verifier que tout fonctionne correctement en lancant par exemple la commande suivante depuis plusieurs terminaux differents (elle envoie de facon repetitive le contenu du binaire "/bin/ls" au serveur, et fait un checksum de la reponse):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    while true; do nc -q 1 127.0.0.1 1234 < /bin/ls | md5sum; done
    le md5sum te permet de controler de facon empirique que chaque thread gere correctement son contexte.

    il faut cependant garder a l'esprit que chaque processus a des resources limitees (nombre de sockets ouverts, en particulier). ici, tous les threads (tcpthread) font partie du meme processus.. si tu as besoin de gerer simultanement un nombre tres important de connexions, il faut envisager de creer plusieurs processus fils, puis plusieurs threads par processus.

    -pirus.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2006
    Messages : 52
    Par défaut
    ok, mais ds le programe , les thread font des read et des write sur la sockets sans tenir compte d aucun mutex ....

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 86
    Par défaut
    Citation Envoyé par nivose110
    ok, mais ds le programe , les thread font des read et des write sur la sockets sans tenir compte d aucun mutex ....
    il n'est pas necessaire de placer de mutex ici; chaque thread obtient son propre socket (le retour de accept() est un nouveau socket).

    en d'autres termes, les mutex sont necessaires lorsque plusieurs threads sont susceptibles de manipuler une meme resource au meme moment, ce n'est pas le cas ici.

    la seule resource partagee entre les threads est la structure tCtx. le controle de l'acces a ses elements (en particulier ctx_count) se fait via un mutex (et une "condition variable").

    -pirus.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2006
    Messages : 52
    Par défaut
    hummmm ok. Cette methode m a l air vraiment pas mal !!!

    Mais une derniere chose me gene .

    Alors imaginons que l on a X thread. Imaginons que les X threads sont pris (par donc X clients), Un X+1 eme client se connect, il devra attendre que l un des thread est fini avec un client. Un fois que tun thread ait fini, il lui reste plus qu a refaire un accept c ca pour accepter la connection du client X+1 ? (evidemment le thread aura dermer la socket), car dans le programme donne, le thread une fois qu il a traite un client, il se ferme.
    De plus ne serait il pas mieux de creer les thread suivant le nombre de clients aulieu de creer X thread et X-n seront endormis en attente de nouveau clients ?

    Genre le main genre gere les accepts et cree un thread avec en parametre la socket.

  6. #6
    Membre éprouvé
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Par défaut
    Citation Envoyé par nivose110
    De plus ne serait il pas mieux de creer les thread suivant le nombre de clients aulieu de creer X thread et X-n seront endormis en attente de nouveau clients ?

    Genre le main genre gere les accepts et cree un thread avec en parametre la socket.
    creer // detruire des threads est couteux en ressource, si 10 clients se connectent simultanement, tu met ton server sur les genoux.

    pour un server qui gere moins d'une centaine de clients (ca depend de l'application aussi), une solution avec select marche TRES bien.

    tu utilise un thread qui fait tourner ton select et utilise une pipe (ou des tableaux de char pour rester portable) et des mutex.
    tu reçois un truc, tu debloque un mutex, le main fait le traitement et rempli un autre tableau de char puis debloque un mutex sur lequel attendais ton thread 'gestion client' (avec le select) et envoi ton message.
    bien sur cette methode n'est pas tres efficace si le traitement et/ou le nombre de clients est important.
    je pense que pour pouvoir te conseiller correctement il faudrais que l'on ait plus de precisions sur la fonction de ton server.
    de plus, il y'as de tres bon specialistes reseaux dans le forum consacré aux reseaux ...

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 86
    Par défaut
    desole pour la reponse un peu tardive, j'etais sur la route..

    effectivement, une fois qu'un thread se termine, il ferme son socket, mais il ne s'agit pas du socket en listen (auquel on ne touche jamais, il reste toujours ouvert par le thread principal), il s'agit d'un socket connecte (donc associe a un client)

    essaye avec X = 2 par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ./tcpserver 1234 2
    puis lance 3 telnet depuis 3 terminaux differents, et regarde si le comportement du serveur correspond a ce que tu attends.

    pour ce qui est de la gestion dynamique du nombre de threads, tu as raison, ca peut etre interessant. je ne l'ai pas fait pour deux raisons:

    • le but etait de presenter un exemple simple de synchronisation autour de accept(), un nombre arbitraire de threads s'y pretait tres bien (sans alourdir inutilement le code),
    • il aurait fallu choisir (arbitrairement aussi) une politique de creation/suppression des threads, selon moi, ce choix doit etre fait en fonction de l'application.


    cependant, tu peux modifier la variable nthr afin de faire varier dynamiquement le nombre de threads. il n'y a rien d'autre a faire (pas de table a redimensionner, etc..). de plus, la methode qui consiste a utiliser une combinaison de threads "detached" et une "condition variable" pour la notification du thread principal apporte beaucoup plus de souplesse qu'un pthread_join().

    tu dois assez facilement pouvoir en faire ce que tu veux, a partir du moment ou tu as decide d'une politique d'allocation de threads. puis bon, c'est juste un exemple.. meme si je me plais a penser qu'il-y-a des choses interessantes a y piocher, je ne pretends pas que ce soit forcement la solution qui te convient le mieux.

    -pirus.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 86
    Par défaut
    Citation Envoyé par Dark_Ebola
    pour un server qui gere moins d'une centaine de clients (ca depend de l'application aussi), une solution avec select marche TRES bien.
    ce n'est pas moi qui vais dire le contraire, j'ai ete pendant longtemps partisan du "select() only"

    comme tu le dis, tout depend de l'application.

    -pirus.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2006
    Messages : 52
    Par défaut
    ok mon serveur recois une chaine de caracteres et la parse pour connaitre les information demander par le client, le server alors recupere les informations dnas les fichiers correspodant et les envoie au clients.
    Il n y a pas de grosses operations, par contre le nombre de client peu etre grand.



    creer // detruire des threads est couteux en ressource, si 10 clients se connectent simultanement, tu met ton server sur les genoux.
    C est vraiment couteu ?? Moi j ai juste besoin de creer les thread. La des truction ce fera jamais normalement, sauf si on veut fermer le server.

    tu utilise un thread qui fait tourner ton select et utilise une pipe...
    Donc il y a 2 threads, 1 pour lire la socket et 1 autre pour la gestion.
    Ce que je ne comprend pas, c est l interet d avoir 2 thread car les operations des 2 threads peut etre fait par un seul thread sans que ce soit beacoup plus long car une fois que le thread ai lu sur la socket, il doit attendre la fin de l autre thread pour relire la socket non? A moins que tu cree un thread a chaque fois si necessaire (mais ca m etonnerait vu ce que tu a dis plus haut).

    De plus pourquoi utiliser le select alors qu il n y a qu un seul port d ecoute (a moins que se soit pour gerer les timout).

  10. #10
    Membre éprouvé
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Par défaut
    l'interet (dans mon cas personnel) de separer gestion clients et gestion data en 2 threads et de pouvoir si le nombre de clients augmente, creer un nouveau thread de gestion des clients.

    en effet, le nombre de socket que peux surveiller select est limité (1024 sur linux et 125 je crois sur windows :: valeurs dependante de l'implementation)

    je pense que chaque server est unique parce qu'il repond a des besoins differents.

    ---

    j'utilise select parce que je suis le plus souvent dans le mode connecté, donc un socket descriptor par connection.
    dans le mode non connecté, tu peux te passer de select et avoir a peu pres le meme comportement.

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2006
    Messages : 52
    Par défaut
    ok.

    derniere chose.
    Chaque thread du server a une socket client differente.
    Je voulais savoir si je devais mettre un mutex lorsque un thread envoie un message a un client?
    J ai fais un petit test apparement ce n est pas la peine mais je voulais avoir confirmation.

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 86
    Par défaut
    Citation Envoyé par nivose110
    Chaque thread du server a une socket client differente.
    Je voulais savoir si je devais mettre un mutex lorsque un thread envoie un message a un client?
    J ai fais un petit test apparement ce n est pas la peine mais je voulais avoir confirmation.
    ce n'est pas necessaire, a partir du moment ou chaque thread utilise son propre buffer pour les I/O bien sur. chaque socket connecte est une resource unique et independante (le fait qu'elles soient issues d'un accept() sur un autre socket ne cree pas de dependance ni entre elles, ni avec l'autre socket).

    si tu as une BU pres de chez toi, regarde si tu peux trouver "Programming with Unix threads" (ou "Programmer avec les threads Unix" dans l'edition francaise, mais comme toujours dans ce cas, gare aux ayatollah de la francisation qui vont jusqu'a editer les commentaires dans le source original de l'auteur.. et parfois introduire des erreurs dans le code :/). ce bouqin contient de nombreux exemples qui peuvent sans doute t'interesser.

    Edit: n'oublie pas la remarque de Dark Ebola concernant la limitation des resources systeme allouees a chaque processus..

    -pirus.

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    86
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 86
    Par défaut
    Citation Envoyé par nivose110
    Alors imaginons que l on a X thread. Imaginons que les X threads sont pris (par donc X clients), Un X+1 eme client se connect, il devra attendre que l un des thread est fini avec un client. Un fois que tun thread ait fini, il lui reste plus qu a refaire un accept c ca pour accepter la connection du client X+1 ? (evidemment le thread aura dermer la socket), car dans le programme donne, le thread une fois qu il a traite un client, il se ferme.
    excuse-moi, je n'avais pas correctement compris ta question..

    effectivement, dans l'exemple chaque thread meurt apres avoir gere une transaction (un session TCP), puis il est remplace par un nouveau thread. la solution alternative consiste effectivement a boucler sur un accept(); cela presente sans doute l'avantage de supprimer la charge systeme associee a la creation des threads, mais ca peut compliquer une eventuelle gestion dynamique du nombre de threads (puisque les threads ne meurent jamais dans ce cas).

    a toi de voir la methode qui te convient le mieux. j'avoue que le "reflexe" de terminer le thread a la fin de la session TCP vient directement du fait que dans le cas d'un serveur multi-process, le fait de terminer le processus et d'en relancer un autre permet de s'assurer que toutes les resources associees (descripteurs, memoire, etc..) sont liberees; hors, ce n'est pas le cas dans un serveur multi-tread, ou il est vraiment indispensable d'etre rigoureux dans la gestion des resources (eviter les memory leak, etc..), puisque tous les threads appartiennent au meme processus.

    -pirus.

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

Discussions similaires

  1. Arrêt d'un serveur multithread
    Par bambou dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 07/07/2010, 16h04
  2. Question Serveur Multithread
    Par Mr_Chut dans le forum Réseau
    Réponses: 10
    Dernier message: 09/06/2006, 17h27
  3. [Conception] Serveur distant
    Par keil dans le forum Général Java
    Réponses: 8
    Dernier message: 26/02/2006, 09h27
  4. Réponses: 5
    Dernier message: 11/01/2006, 07h58

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