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 :

De la non utilisation du fork


Sujet :

Réseau C

  1. #1
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Par défaut De la non utilisation du fork
    Bonjour,

    Je suis en train de réaliser un serveur en C pour un projet. Pour information je suis sous environnement UNIX (darwin). Je me suis un peu documenté, c'est un peu compliqué sachant que les mans peuvent être quelquefois très mal faits.

    Bref, j'ai regardé quelques exemples et tous, après le accept, utilisent un fork() pour régler le problème des sockets bloquantes. Pour ma part, je ne suis pas particulièrement fan de cette solution, et je me demandais si c'était la meilleure.

    Ainsi, j'ai plutôt imaginé la structure de mon système ainsi :
    - Le serveur, lancé par launchd, fait un unique fork (ou bien lance directement un binaire différent) pour lancer le démon de traitement, les deux sont reliés par deux pipes. Il s'occupe de l'interface avec le réseau, connecte et déconnecte les clients, parse les requètes (en XML), et les transmet au démon de traitement.
    - Le démon de traitement reçoit les données de tous ses clients par une seule pipe, les traite, et en envoie au serveur par la seconde pipe, lequel dispatche aux clients.

    Ainsi, le serveur ressemblerait à cela :

    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
    exec('démon de traitement');
       => pipe('to démon de traitement');
       => pipe('from démon de traitement');
     
    socket/bind('connexion extérieure'); => fcntl('non bloquante');
     
    while(1)
    {
     
        accept('eventuel client'); => fcntl('non bloquante');
     
        if(select('lecture pipe et connexions'))
        {
            recv('pipe from'); => send('client');
            for('chaque client')
            {
                recv('client'); => send('pipe to');
            }
        }
     
    }
    Et le démon de traitement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while(1)
    {
     
        if(select('lecture pipe'))
        {
            recv('pipe to'); => traitement(); => send('pipe from');
        }
     
    }
    Ainsi, amha, il n'y aurait pas besoin pour le démon de traitement de s'occuper de toute la gestion réseau et cela règlerait énormément de problème. Seulement, je n'ai jamais fait de programmation sockets auparavant et je voudrais valider ma méthodologie :
    - Est-ce une façon viable de faire ? Y a-t-il des importants points de blocage que je n'aurais pas vu ?
    - Est ce que j'aurais besoin de mettre un test en écriture vers les sockets dans le select du serveur ou bien est ce que le tampon du système est assez grand pour ne jamais être overflowé ?
    - Du coup, est ce que j'aurais besoin de tampons au niveau du serveur pour transmettre les données des connexions à la pipe et vice versa ?

    Merci de vos réponses et éclaircissements, si vous avez des remarques supplémentaires, n'hésitez pas.

  2. #2
    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
    quel usine a gaz

    pourquoi ne pas utiliser select tout seul? sans fork et autres pipes?

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Par défaut
    Parce que j'ai envie d'avoir une partie de traitement complètement indépendante du réseau. Genre que le traitement puisse tourner alors que le serveur ne transmet rien, ou l'inverse. Et que cela me semble peut être plus simple à mettre en œuvre.
    Mais je suis ouvert à d'autres possibilités, tu as quelquechose à me proposer pour fusionner les deux ?

  4. #4
    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
    Pourquoi pas des threads ? (même si je suis souvent de l'avis qu'il vaut mieux utiliser des select au lieu de faire intervenir des threads ou processus supplémentaire).

    La création de thread mettent en général 15 fois moins de temps qu'une duplication de processus avec fork et permet d'éviter de bouffer de la mémoire pour rien (puisque seul une nouvelle pile est crée)

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Par défaut
    Pourquoi pas des threads ? Réponse simple : trop galère.
    Je suis conscient que ce serait une des meilleures solutions. Cependant c'est un petit projet pour lequel je n'aurais pas le temps d'apprendre la mise en œuvre et surtout de maîtriser l'utilisation des threads. Je dois par ailleurs avouer que j'avais dès le début complètement exclu cette option. A moins que l'on me fasse mentir, les threads sont tout de même (de l'aveu de certains de mes amis) assez complexes à intégrer. Par ailleurs, j'ai déjà les problèmes de socket à régler, je n'ai pas envie de devoir gérer en plus ceux que j'aurais avec les threads.

    Pour le coup, deux processus distincts seraient beaucoup plus simples à coder. Après, serait-ce une solution viable ? Quelle serait ses limites fasse à une solution select ou bien une solution threads ? Y aurait-il quelqu'un pour une comparaison/explication des 3 options ?

  6. #6
    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
    Effectivement, les threads, c'est galère. C'est difficile à débugguer, c'est difficile à coder proprement. C'est pourquoi on utilise souvent (en C) des solutions à base de select jusqu'à ce que l'intervention des threads soient nécessaires (ou rende le code plus simple)

    Par ailleurs, j'ai déjà les problèmes de socket à régler, je n'ai pas envie de devoir gérer en plus ceux que j'aurais avec les threads.
    Dans ce cas, évite absolument les threads et concentre toi uniquement sur les sockets. Il est possible de faire à peu près tout rien qu'avec des select. Mais si tu penses que la solution avec fork te parait plus simple, fait comme tu le sens.

  7. #7
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Par défaut
    D'accord, merci de ta réponse. Je vais déjà débugguer ce que j'ai fait (cf je pense un futur topic).
    Je suis ouvert à d'autres réponses ou avis, je laisse ce sujet ouvert.

  8. #8
    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
    il existe plusieurs écoles, chacune avec ses avantages et inconvénients:

    • threading: consiste à créer un thread, voir un processus complet (fork)
    pour chaque nouveau client.
    avantage: simple à coder
    inconvénient: peu performant

    • mode non bloquant: les sockets sont paramétrés en mode non bloquant,
    les opérations de lecture/écriture retournent immédiatement une valeur
    caractéristique pour indiquer qu’elles auraient du bloquer.
    avantage: - (si quelqu'un en vois un, quil me fasse signe)
    inconvénient: utilisation CPU élevée.

    • multiplexage: on confie notre ”pool” de sockets `a une fonction tel que
    select ou poll qui vont se charger d’indiquer sur quels sockets on est capable
    d’effectuer une action non-bloquante.
    avantage: centralisation des fonctions blocantes
    inconvénient: code plus complexe

    et bien sur tout un tas d'hybrides de ces 3 méthodes.

  9. #9
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Dark_Ebola Voir le message
    • mode non bloquant: les sockets sont paramétrés en mode non bloquant,
    les opérations de lecture/écriture retournent immédiatement une valeur
    caractéristique pour indiquer qu’elles auraient du bloquer.
    avantage: - (si quelqu'un en vois un, quil me fasse signe)
    inconvénient: utilisation CPU élevée.
    .
    J'avoue ne pas comprendre ton point, la...

    La definition meme d'un mode non-bloquant est qu'il ne bloque pas

    Et donc, couple a signal(), on est averti UNIQUEMENT quand il se passe quelque chose sur le socket (pour lire). Donc 0 CPU (ou alors c'est qu'on est en train de faire autre chose)...

    Avantage : ne travaille que quand on abesoin
    Inconvenient : implementation plus difficle sur Windows que sur unixoide

  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
    ce que jappelle mode non bloquant est lutilisation dun sockett avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fcntl(sockfd, F_SETFL, O_NONBLOCK);
    et ensuite faire du polling sur les fonctions de lecture//ecriture (recv//send)

    cest tres mauvais question utilisation CPU, cest plus delicat a coder (a mon sens)...

    envoyer un signal quand un descripteur est pret ... ,pourquoi pas ... mais pourquoi ne pas utiliser select//poll a ce moment là?

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Dark_Ebola Voir le message
    ce que jappelle mode non bloquant est lutilisation dun sockett avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fcntl(sockfd, F_SETFL, O_NONBLOCK);
    et ensuite faire du polling sur les fonctions de lecture//ecriture (recv//send)

    cest tres mauvais question utilisation CPU, cest plus delicat a coder (a mon sens)...

    envoyer un signal quand un descripteur est pret ... ,pourquoi pas ... mais pourquoi ne pas utiliser select//poll a ce moment là?
    je n'ai jamais vu utiliser la methode que tu decris..

    Quand on utilise fcntl ... O_NONBLOCK en general on couple avec signal().

    signal() sert a signaler qu'il s'est passe quelque chose sur le socket.
    poll() sert a verifier si il y a bien quelque chose a lire, ou alors une erreur (socket gele, client deconnecte, etc..)

    et select/poll justement empeche de faire autre chose en parallele...

    Prenons le cas :

    une IHM recevant des donnees - aleatoirement dans le temps - mais pouvant faire tour un tas de trucs demandes par l'utilisateur, dont des boucles d'affichage etc etc..

    Il y a bien une "main loop" de gestion des evenements graphiques, qui peut etre elle-meme "sous-traitee" dans une boucle d'affichage continue..

    Mais si maintenant tu mets un select... hum humm...

    Alors que si tu mets un signal(), tu n'es averti QUE quand quelque chose arrive.. La tu peux modifier tes strucures, tableaux, et autres, dynamiquement, et reprendre ta boucle ou tu en etais.... Sans avoir a aller verifier a chaque tour...

    Donc vraiment 0 CPU, sauf quand le socket est reveille et donc le signal envoye.. La on va faire le poll pour voir si ily a vraiment quelque chose a lire, ou si c'est une erreur...


    Enfin c'est comme ca que moi je l'utilise...

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    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 397
    Par défaut
    Donc, avantage: Ne travaille que quand on a besoin
    Inconvénient: Modèle de programmation plus compliqué (prog. interruptible vs. prog. événementielle).
    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.

  13. #13
    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
    (mince, une de mes reponses as saute, mais medinoc resume ca plutot bien )

    a rajouter aussi que select peut etre non bloquant, (meme avec des sockets bloquants) voir les details de son dernier parametre

    timeout est une limite supérieure au temps passé dans select avant son retour. Elle peut être nulle, ce qui conduit select à revenir immédiatement. (Ce qui sert pour des surveillance en polling). Si le timeout est NULL (aucun), select peut bloquer indéfiniment.

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    timeout est une limite supérieure au temps passé dans select avant son retour. Elle peut être nulle, ce qui conduit select à revenir immédiatement. (Ce qui sert pour des surveillance en polling). Si le timeout est NULL (aucun), select peut bloquer indéfiniment.

  15. #15
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    613
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 613
    Par défaut
    struct timeval *timeout

    NULL != (timeout->* == 0)

    Enfin c'est ce que j'ai compris.

    D'ailleurs c'est bien précisé NULL (aucun), c'est à dire pointeur NULL et pas valeur nulle

  16. #16
    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
    struct timeval m_time = {0}; => non bloquant
    NULL => bloquant

  17. #17
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    je le sais bien..

    Mais j'aurais plutot mis "La valeur peut etre nulle (0), ce qui conduit.... Si le pointeur sur la structure est mis a NULL.. "

    Car la, de la maniere dont c'est dit, c'est plutot.. confusant...

  18. #18
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Par défaut
    Bon, je vois que le sujet avance

    Pour l'utilisation de signal(), ça m'intéresse, j'avais essayé, mais il ne faisait jamais ce qu'il fallait (par contre, je suis désolé, je n'ai plus les sources, j'ai rapidement laissé tomber). Il faut utiliser quel signal pour tester l'existence de données entrantes ? Parce que le seul signal que j'avais trouvé ne le faisait que lorsque l'on recevait des données urgentes, ce qui ne m'intéressait pas…

  19. #19
    Membre expérimenté
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Par défaut
    Quelqu'un aurait-il une idée du signal que je dois utiliser ?
    Merci.

  20. #20
    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

Discussions similaires

  1. Non-utilisation d'un caractère générique
    Par ehrhart.jy dans le forum Access
    Réponses: 2
    Dernier message: 13/07/2006, 11h02
  2. [TUNING] pb non utilisation de l'index
    Par ruthene dans le forum Oracle
    Réponses: 10
    Dernier message: 13/04/2006, 17h02
  3. Javascript : non utilisation du CSS
    Par lafracas dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 12/04/2006, 09h49
  4. [SERVICE INTERACTIF] Form non utilisable apres logoff/logon
    Par Spart64 dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 05/03/2006, 13h32
  5. Réponses: 1
    Dernier message: 28/04/2004, 19h36

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