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 :

[Réseau] Ecoute de port et connections simultanée


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    177
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 177
    Par défaut [Réseau] Ecoute de port et connections simultanée
    Bonjour,

    J'aimerais réaliser un programme gérant les accès à un serveur. Mon soucis ne vient pas directement du C++, mais plutot d'un problème théorique :

    Mon programme écoute un port donné. Lorsqu'il reçoit quelque chose, il traite la demande en direct : en gros il reçoit un identifiant, et un mot de passe, il vérifie dans la BDD s'il existe, puis retourne un résultat au client.

    Ma question est de savoir ce qu'il arrive, si pendant ce traitement, une ou plusieurs autres demandes arrivent? Seront-elles mises dans une file d'attente (un genre de pile FIFO) automatiquement par le système, ou au contraire ces demandes seront elles simplement ignorées, tant que le traitement de la première demande n'est pas terminé?

    Quelle solution apporter? Mettre un thread qui ne fait qu'écouter le port en permanance, et ajouter le pointeur vers cet ordinateur dans une pile manuellement? Mais le soucis est toujours le même si d'autres demandent arrivent pendant ce temps (en cas de très forte affluance).... Mettre plusieurs threads écoutant plusieurs ports? Mais encore faudrait-il que le client sache quel port est disponible...

    Qu'en pensez-vous?

    Je sais que le temps de traitement étant très court (quelques fractions de secondes), le problème ne devrait pas se produire très souvent. Cependant, j'aimerais savoir s'il est possible que cela arrive, et s'il on peux l'éviter.

    Merci d'avance pour vos réponses!

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Les connexions non satisfaites sont mises en file d'attente, selon le second paramètre de listen().
    Au-delà, je ne sais pas ce qui est censé se passer: Peut-être que la connexion est explicitement refusée, ou que le serveur ne répond simplement pas (poussant le connect() à réessayer automatiquement jusqu'au timeout)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Pour ce genre de situation, il y a bien une architecture optimale.
    Celle-ci consiste mettre en place un thread qui attend de nouvelles connexions. Lorsqu'il y a une demande qui arrive, il passe la socket client à un thread faisant partie d'un pool de thread. Un pool de thread en gros c'est un nombre limité de threads qui tournent en permanence. On peut en réserver un mais il ne sera à nouveau disponible que quand il aura terminé sa tache. Cette solution présente le double avantage multi utilisateur+limitation du nombre de connexions (indispensable pour un serveur résistant).
    Bon, même si c'est ce qu'il y a de mieux, ce n'est pas forcément simple à faire
    Alors je te propose deux autres solutions:
    - Même principe que plus haut mais il n'y a pas de pool. C'est à dire que pour chaque connexion entrante un thread est créé. Généralement pour des dossiers scolaires ça fonctionnera toujours bien.
    - Un serveur monothread. Le serveur reçoit une demande, fais le traitement et renvoie la réponse. En dehors du fait que c'est la pire solution point de vue performance, il est impératif que ton protocole soit déconnecté, c'est à dire qu'il n'ait aucun besoin de maintenir une connexion permanente (donc comme http mais pas du tout comme ftp). Et oui, si une demande arrive pendant que ton serveur traite une autre demande elle sera mise en attente. Il n'y a que l'hote distant qui pourra décider de laisser tomber si le délais d'attente est trop long (une dizaine de secondes, ça ne signifie pas qu'il soit agréable pour l'utilisateur d'attendre dix secondes!).
    PS: laisse tomber cette idée de plusieurs ports, on a tous fait ce genre d'erreur de conception au début mais avec le recul c'est vraiment ridicule.

  4. #4
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    177
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 177
    Par défaut
    Merci pour vos réponses.

    Pour résumer la "meilleure" solution :
    - 1 thread s'occupe d'écouter un port
    - Ce thread principal ajoute la socket à une liste des demandes en attente (liste accessible à partir des autres threads)
    - x threads s'occupent de traiter 1 à 1 chaque demande listée dans cette liste.

    On est bien obligé de passer par une liste non? Tu n'en parles pas, mais je suppose que ce serait plus simple que de devoir à chaque fois trouver un thread disponible (sans parler du cas à prévoir si tous les threads sont déjàs occupés)...


    Par contre tu disais qu'en terme de performance, un monothread était la pire solution, mais je ne vois pas pourquoi : je connais le principe du thread, qui est de réaliser des actions en parallèle. Par contre, en terme de performance, je doute qu'il y aie un gain : entre 3 threads qui tournent en permanance et donc se partagent en trois la puissance de calcul du processeur, et dont il faut du temps pour switcher entre chaque thread, et 1 seul utilisant tout la puissance de calcul du processeur, et sans temps de switch, l'avantage reviendrait logiquement au monothread
    Idem en termes de mémoire : un seul thread consommera moins de mémoire vive que 3 tournant en permanance

    Ai-je mal compris quelque chose?

  5. #5
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Il faut bien comprendre que dès que l'on fait intervenir des threads, il y a des difficultés importantes qui arrivent (il faut que l'application soit multithread safe).

    Si les traitements clients a effectués sont légers, il est possible d'utiliser un select sur l'ensemble des sockets et d'avoir une application monothread performante.

    Par contre, dès qu'il y a des traitements lourds (par exemple envoi d'un fichier, attente pendant un certain temps), il est conseillé de faire intervenir un thread à ce moment lent.

    Souvent, les gens ne se prennent pas la tête et font un thread par client : il est toujours possible de limiter le nombre de client pour éviter que l'application rame (donc le nombre de thread).


    Il faut savoir que contrairement au processus, le basculement entre deux threads est nettement plus rapide qu'entre deux processus (d'un ordre de 30 je crois), donc ce n'est pas vraiment un soucis.

    Faire intervenir des threads peut également simplifier conceptuellement l'application.


    A toi de voir

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Citation Envoyé par ChriGoLioNaDor Voir le message
    On est bien obligé de passer par une liste non? Tu n'en parles pas, mais je suppose que ce serait plus simple que de devoir à chaque fois trouver un thread disponible (sans parler du cas à prévoir si tous les threads sont déjàs occupés)...
    Tout dépend de la conception du pool de thread, que l'on concevra généralement de manière générique. Il peut par exemple être fait, comme tu le suggère, avec une queue de taille limitée, la on a pas vraiment une limite du nombre de connexion mais du nombre de demandes, et on repart dans le protocole déconnecté. Un pool de thread simple avec limite du nombre de connexions sera en général fait en jouant avec des mutex/sémaphores.

    Citation Envoyé par ChriGoLioNaDor Voir le message
    Par contre tu disais qu'en terme de performance, un monothread était la pire solution, mais je ne vois pas pourquoi : je connais le principe du thread, qui est de réaliser des actions en parallèle. Par contre, en terme de performance, je doute qu'il y aie un gain : entre 3 threads qui tournent en permanance et donc se partagent en trois la puissance de calcul du processeur, et dont il faut du temps pour switcher entre chaque thread, et 1 seul utilisant tout la puissance de calcul du processeur, et sans temps de switch, l'avantage reviendrait logiquement au monothread
    Idem en termes de mémoire : un seul thread consommera moins de mémoire vive que 3 tournant en permanance

    Ai-je mal compris quelque chose?
    Tu te trompes, tu ne vois pas toutes les subtilités. Ta logique serait bonne si le role d'un serveur était de recevoir de petites données, faire de gros calculs dessus et puis renvoyer une petite réponse. Je ne dis pas que ça n'existe pas, mais en général on se servira d'une calculatrice pour ça .
    Le plus souvent un serveur a pour but de distribuer ou de stocker des informations, à partir de fichier pour les cas simples, d'une base de données la plupart du temps. C'est à dire que le temps de calcul ne vaut pas le centième du temps transfert client->serveur+transfert serveur->bd+temps de traitement bd+transfert bd->serveur+transfert serveur->client. Un serveur passe la plupart de son temps à attendre, d'où l'utilité du multithread, parcequ'un thread qui attend ne ralentis pas les autres.
    Qui plus est, il faut penser à tous les utilisateurs. Il est bien plus équitable d'avoir 10 utilisateurs simultanés qui recoivent leur réponse en même temps plutot que de faire attendre éternellement ceux qui ont eu le malheur d'arriver en dernier. Imagine un serveur ftp, avec de gros fichiers qui prennent plusieurs heures pour le transfert, tu imagines si tu devais attendre aussi longtemps avant que la reception de ton fichier ne commence?

  7. #7
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    177
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 177
    Par défaut
    Oui en effet, en cas de traitement long (transfert de gros fichiers par exemple, ou encore attente d'une réponse du client), ou d'actions simultanées (on veux pendant le transfert afficher une barre indiquant le pourcentage d'avancement), le multithread est obligatoire ou presque.

    Je parlais surtout de mon cas : un programme autonome qui ne s'occupe que de recevoir login+mdp, fait une recherche dans une BDD pour savoir si tout est OK, puis renvoie une réponse (par exemple un identifiant unique, ou tout simplement un booléen). Il n'y a donc aucun traitement long, à part à la limite l'accès à la BDD, qui se fait en local.

    Dans ce cas précis, je serais plutot contre la création d'un thread par client : le temps de sa création et de sa destruction risque de ne pas être négligeable par rapport au temps d'exécution...

    Par contre en effet, la création de x threads permanants et d'un thread "d'écoute" pourraient être une autre solution envisageable, mais j'essaie justement de voir s'il y aurait un gain réel dans ce cas précis. Mais d'un coté, il est vrai que cela permettrait aussi de ne pas bloquer le programme en cas de soucis avec un client (transfert des données anormalement lent, mauvaise communication, ...).


    PS : je vais réviser mes mutex/sémaphores. Je connais ces termes, mais ne me rappelle plus leur utilité précise, depuis le temps ^^. C'est bien ce qui permet de créer des sections critiques (par exemple pour accéder et modifier les données de ma liste) ? :p

Discussions similaires

  1. Ecouter un port sur un réseau
    Par zouheir dans le forum Entrée/Sortie
    Réponses: 12
    Dernier message: 16/08/2006, 02h03
  2. Réseau local par ports usb ?
    Par progfou dans le forum Hardware
    Réponses: 3
    Dernier message: 17/03/2006, 20h59
  3. [Système] Ecouter un port serveur Java
    Par sozie9372 dans le forum Langage
    Réponses: 3
    Dernier message: 19/01/2006, 21h35
  4. Ecouter le port de téléphonie sur IP
    Par WOLO Laurent dans le forum Développement
    Réponses: 6
    Dernier message: 24/09/2005, 12h43
  5. [UDP][Socket] perte de paquets et arret d'ecoute sur port
    Par Guismo1979 dans le forum Développement
    Réponses: 6
    Dernier message: 02/01/2003, 12h13

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