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 :

Questions sur la gestions des processus d'un serveur


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut Questions sur la gestions des processus d'un serveur
    Bonjour,

    Je suis en train d'essayer de programmé la partie serveur d'un jeux et je me pose plusieurs questions sur le C dans le but de consommer un minimum de ressource tout en étant le plus rapide possible :

    1) Pour vérifier qu'un serveur est en ligne, je peux établir une socket toutes les minutes pour chaque client (sans qu'ils se soient connectés), mais n'y a-t-il pas de méthodes moins coûteux?

    2) Pour ce qui est des ports, faut-il associer un port par client? un port pour x client? (si oui comment choisir ce x?) ou un port pour tous les clients?
    J'ai fait quelques recherches, et il semblerait que les n° de ports servent à définir l'application de destination du message pour éviter de "s'embrouiller" mais chaque client aura un processus dédiés au traitement de ses messages.


    3) Pour la communications entre processus, on a les tubes et la mémoire partagée.
    Les tubes sembles intéressant pour la discutions de processus 2 à 2 et la mémoire partagée pour la discutions entre un grand nombre de processus.
    Mais quels sont les avantages et les défauts de chacun?

    4) Pour les tubes, il me semble qu'on fait un fopen("nom", "w") et un fopen("nom", "r") pour le créer mais plus le tube sera utiliser plus il va "grossir", comment faire pour vider le début dont on a pas besoin?
    (il faut aussi faire un fopen("nom", "r") après chaque modification il me semble non?)

    5) Beaucoup de processus du serveur vont fonctionner par scrutation, c'est assez dommage...
    J'ai dans l'idée de leur faire des sleep(x) s'ils se réveillent au bout de x secondes, ils font un "time out"
    Et lors de la réception d'un message, un interruption réveille (SIGCONT) le processus concerné qui traitera le message et réveillera les autres processus impliqués. Est-ce une bonne idée?

    J'essaye de faire des recherches internet, mais je n'arrive pas à trouver des explications plus approfondies qui me permettrais de trouver les réponses à mes questions.

    Merci de m'avoir lu,

    Neckara

  2. #2
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut
    Salut,

    La première chose que j'ai à dire c'est que la plupart des questions que tu poses ne sont pas claires. J'ai fais aboutir un projet similaire donc je vais essayer d'apporter ma modeste contribution et te dirai quand je suis pas sûr d'avoir compris.

    Citation Envoyé par Neckara Voir le message
    1) Pour vérifier qu'un serveur est en ligne, je peux établir une socket toutes les minutes pour chaque client (sans qu'ils se soient connectés), mais n'y a-t-il pas de méthodes moins coûteux?
    Tu peux toujours faire un petit protocole basé sur de l'UDP qui marchera un peu comme un ping. Tu bind ton serveur sur la socket et lorsque le client veut vérifier si le serveur est là il envoie un packet sur le port et si le serveur ne répond pas c'est qu'il n'est pas en activité. Je t'aurais bien proposé un broadcast mais cette solution a pour avantage de ne pas restreinte ton serveur au sous-réseau.

    Citation Envoyé par Neckara Voir le message
    2) Pour ce qui est des ports, faut-il associer un port par client? un port pour x client? (si oui comment choisir ce x?) ou un port pour tous les clients?
    J'ai fait quelques recherches, et il semblerait que les n° de ports servent à définir l'application de destination du message pour éviter de "s'embrouiller" mais chaque client aura un processus dédiés au traitement de ses messages.
    Ben le mieux selon moi ce serait encore de faire le principe du ssh. Le serveur fork ou ouvre un thread pour chaque client et communique via un autre port. De cette façon tu n'as pas à faire le tri des packets reçus et le port "officiel" sert seulement à l'établissement de la connection. C'est la solution la plus rapide et la moins consommatrice que je connaisse.


    Citation Envoyé par Neckara Voir le message
    3) Pour la communications entre processus, on a les tubes et la mémoire partagée.
    Les tubes sembles intéressant pour la discutions de processus 2 à 2 et la mémoire partagée pour la discutions entre un grand nombre de processus.
    Mais quels sont les avantages et les défauts de chacun?
    Là par contre je comprends pas très bien. Tu parles de quels processus? Ceux des clients et serveurs ou ceux que le serveur va créer? Parce que si tu parles des clients et serveurs oublies les 2 solutions. Si tu parles des processus du serveur, moi je te conseillerai la mémoire partagée et des mutex et sémaphore. Parce que les tubes devronts être lu via un gestionnaire. C'est plus sûre mais c'est plus lent.

    Citation Envoyé par Neckara Voir le message
    4) Pour les tubes, il me semble qu'on fait un fopen("nom", "w") et un fopen("nom", "r") pour le créer mais plus le tube sera utiliser plus il va "grossir", comment faire pour vider le début dont on a pas besoin?
    (il faut aussi faire un fopen("nom", "r") après chaque modification il me semble non?)
    Non. Pour les tubes tu fais un pipe directement. Mais le tube ne grossit pas! C'est le même système que stdin et stdout. Il n'y a que le buffer interne qui grossira si les infos ne sont pas lues (d'où mon conseille de mémoire partagée) mais lorsqu'elles sont lues, l'espace est libéré.

    Citation Envoyé par Neckara Voir le message
    5) Beaucoup de processus du serveur vont fonctionner par scrutation, c'est assez dommage...
    J'ai dans l'idée de leur faire des sleep(x) s'ils se réveillent au bout de x secondes, ils font un "time out"
    Et lors de la réception d'un message, un interruption réveille (SIGCONT) le processus concerné qui traitera le message et réveillera les autres processus impliqués. Est-ce une bonne idée?
    Pour répondre à çà il faudrait qu'on en sache un peu plus sur les fonctions des processus dont tu parles. Le processus sensé recevoir les données du client un poll() est mieux. Sinon pour les processus interne du serveur un poll sur une socket unix c'est pas mal aussi.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Question 1:

    Si je comprend bien, plutôt qu'établir une socket par demande de vérification de l'accès du serveur, il vaut mieux ne faire qu'une seule socket par client.
    Dans ce cas là, il faudra aussi que le client dise qu'il est lui aussi accessible (mais peut être qu'on s'en aperçoit en cas de non-échec de l’envoi d'un paquet du serveur vers le client?)


    Question 2:

    Donc si je comprend bien je fait un socket par port?
    Je vois comment fonctionne le fork et il me paraît plutôt intéressant, ainsi, plutôt que d'écrire plusieurs programmes avec des fonctions différentes, je n'ai qu'à faire des fork et à définir leur rôles en fonctions qu'il soient fils ou qu'ils soient père. wait(null) permet d'attendre la fin du processus fils, mais le père peut très bien se terminer avant le fils sans problèmes non?
    L'avantage c'est que cela sera plus rapide que de lancer un programme à chaque nouveau client.


    Question 3:

    Pour les communications entre processus, je parlais des processus côté serveurs.
    Pour le client/serveur, j'utiliserais des socket (on m'a d'ailleurs conseillé openSSL).
    Il faudra que je regarde les mutex.

    Question 4: j'ai ma réponse merci

    Question 5: Le problème avec les socket Unix, c'est qu'ils utilisent un protocole réseau interne donc l'échange de donnée est relativement longue, c'est d'ailleurs pour cela que je pense utiliser la mémoire partagée.

    EDIT : je suis bête, je n'ai qu'à lancer des forks pour faire les divers traitements!

    Il n'y a donc que pour les entrée des données clients que je devrais faire de la scrutation.
    Mais peut-être que la scrutation est négligeable?

  4. #4
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Question 1:

    Si je comprend bien, plutôt qu'établir une socket par demande de vérification de l'accès du serveur, il vaut mieux ne faire qu'une seule socket par client.
    Dans ce cas là, il faudra aussi que le client dise qu'il est lui aussi accessible (mais peut être qu'on s'en aperçoit en cas de non-échec de l’envoi d'un paquet du serveur vers le client?)
    Qu'entends-tu par "vérification de l'accès du serveur?". Pour l'accès du serveur, comme je t'ai dit, le mieux c'est de faire un autre processus en UDP qui ne sert qu'à dire "oui le vrai serveur est là!". En UDP pour éviter l'overload du TCP. Un exemple :

    _ Tu as le pid 40000 qui attend sur l'adresse UDP 192.168.1.1:54000.
    _ Tu as ton vrai serveur (du moins le gestionnaire de connection), pid 41000 qui attend sur l'adresse TCP 192.168.1.1:55000.

    Donc au démarrage du serveur tu as déjà 2 processus au minimum.




    Citation Envoyé par Neckara Voir le message
    Question 2:

    Donc si je comprend bien je fait un socket par port?
    Je vois comment fonctionne le fork et il me paraît plutôt intéressant, ainsi, plutôt que d'écrire plusieurs programmes avec des fonctions différentes, je n'ai qu'à faire des fork et à définir leur rôles en fonctions qu'il soient fils ou qu'ils soient père. wait(null) permet d'attendre la fin du processus fils, mais le père peut très bien se terminer avant le fils sans problèmes non?
    L'avantage c'est que cela sera plus rapide que de lancer un programme à chaque nouveau client.
    Non, ce n'est pas Windows Sous Linux lorsque le père se termine, sa descendance aussi. Exception faite des fork "détachés" du père. D'ailleurs c'est le processus normal du démarrage d'un serveur. Un serveur commence par se détacher du processus appelant, ferme stdin et stdout et commence ses tâches.

    Par contre, pour les processus fils dont je parle, vaut mieux au contraire qu'ils restent attachés au père. Les détacher du père serait se compliquer la vie pour rien. Voici ce à quoi je pense.

    Le serveur se lance.
    1) Il lance un fork pour le serveur sensé répondre à ceux qui veulent savoir si le serveur est en activité. Ce serveur bind sur l'adresse UDP 192....1 port X et ne fait rien d'autre qu'attendre des requêtes (poll()).
    2) Le serveur principal (celui qui a lancé le fork() )bind sur l'adresse TCP 192...1 port Y. il ouvre une zone de mémoire partagée et attend des connections.
    Le premier client
    1) Le client envoie un paquet en UDP sur le port X (En fait 3 ou 4 au cas où les paquets ce sont juste perdus. C'est de l'UDP)
    2) Il reçoit une réponse, ok le serveur est en route. Il le contacte en TCP sur le port Y.
    3) Le serveur de jeu reçoit une connection sur le port Y. Il fork.
    4) Le fork renseigne les fonctions des signaux et ouvre le port Z. Il rentre en contacte avec le client (A toi de voir les détails) et traite avec le client par ce port.
    etc...


    Citation Envoyé par Neckara Voir le message
    Question 3:

    Pour les communications entre processus, je parlais des processus côté serveurs.
    Pour le client/serveur, j'utiliserais des socket (on m'a d'ailleurs conseillé openSSL).
    Pourquoi openSSL? on parle bien d'un serveur de jeux? Nan si tu veux des performances optimales laisses tomber les overloads inutiles.


    Citation Envoyé par Neckara Voir le message
    Il faudra que je regarde les mutex.
    Oui renseignes toi bien. Surtout si les 10 joueurs de la même équipe shootent en même temps sur le drapeau ennemis (d'ailleurs je sais pas si ça te parle mais renseignes toi aussi sur les RTS, real-time signals. Ca évitera que tes fils attendent 10 000 ans sur la même ressource.)

    Citation Envoyé par Neckara Voir le message
    Question 5: Le problème avec les socket Unix, c'est qu'ils utilisent un protocole réseau interne donc l'échange de donnée est relativement longue, c'est d'ailleurs pour cela que je pense utiliser la mémoire partagée.
    Effectivement!

    Moi je pensais plutôt à un truc du genre:

    Citation Envoyé par Neckara Voir le message
    *arrivée d'un message*
    → interruption → réveille le processus impliqué (SIGCONT).

    -> Recevoir_client1 se réveille regarde s'il y a un message et traite ce message.
    Si il y a pas de message, il en conclu que le client s'est déconnecté, sinon, il réveille les autre processus impliqué et se rendort pour x secondes.
    Exemple: il reçoit un message pour le canal de chat ''groupe'' il va transmettre le message à Envoyer_client2 et Envoyer_client3 et va les réveiller avec (SIGCONT)

    Ce qui permettrait d'éviter que des processus prennent le CPU pour faire de la scrutation périodique.

    Mais peut-être que la scrutation est négligeable?
    C'est une façon de voir les choses. Personnellement Les deux seuls problèmes que je vois là dedans c'est :
    1) Ce n'est pas vraiment un système real time et il consommera beaucoup plus car avec 10 000 client géré par une seule fonction. Bah y'en a beaucoups qui vont attendre.
    2) Si tu veux un jeux en temps réels tes sleeps seront tellement petits qu'ils ne serviront quasiment à rien.

    L'avantage de ce que je te propose c'est déjà que ton serveur n'a pas à faire le tri dans les paquets reçus (ce qui prends beaucoup de temps). Vu que chaque fils attend sur un port bien précis et sait que les paquets qu'il reçoit vient de son client.

    L'avantage du poll() c'est que le fils n'a pas à se réveiller, c'est le système qui le réveille quand il reçoit un paquet.

    Pour gérer les pertes de connexions. Regarde poll(). Le processus n'a pas à réveiller le système, mais le système le réveille et lui dit pourquoi il l'a réveillé. Si c'est parce qu'il y'a eut une perte de connection, le signal te réveille avec l'info POLL_HUP, si c'est parce que le client a envoyé des donnée, tu reçois l'info POLL_MSG etc... Si tu veux aussi surveiller les inactivités, regardes du côté de alarm().

    J'espère t'avoir été utile.

    Cordialement.

  5. #5
    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
    Note : poll n'est (malheureusement) pas dispo sous Windows....

    D'autre part, pour la question no1, pourquoi particulièrement UDP ?

    Et pourquoi simplement ne pas utiliser un socket asynchrone ???


    Question no2 : cela s'appelle "un service", ce qui est défini (et setté) sur tel ou tel port.

    Et, sous unixoides, cela se passe en "forkant" : le serveur "père" attend (en bloquant) sur ce port. Lorsqu'il reçoit une demande de connexion, il se forke, envoie lesocket de communication au client, et repart en attente.

    Sous Win, je ne sais pas comment ça marche, mais ça doit être le même principe à part que cela doit créer des threads plutôt qu'un autre process

    Il y a tout ce qu'on peut souhaiter dans la rubrique "réseau" ici-même, y compris des exemples de clients/serveurs.

  6. #6
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2009
    Messages
    172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2009
    Messages : 172
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    D'autre part, pour la question no1, pourqoi particulièrement UDP ?
    Parce que si c'est simplement pour savoir si le serveur est alive pas besoin d'alourdir la conversation avec du TCP. Un peu comme un ping.

    Sous windows c'est le même principe sauf qu'au lieu de socket tu attends sur des handles.

    Citation Envoyé par souviron34 Voir le message
    Question no2 : cela s'appelle "un service", ce qui est défini (et setté) sur tel ou tel port.
    Comment çà?

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Je comprend, un port pour signaler*: le serveur est là en UDP
    Un port pour la connexion en TCP
    Par contre il faudrait que je recherche les différences entre UDP et TCP mais je pense pouvoir trouver sur le net.

    Sous Linux, lorsque le processus père meurt, le processus fils n'est pas adopté par init(1)*?


    ''Pourquoi openSSL? on parle bien d'un serveur de jeux? Nan si tu veux des performances optimales laisses tomber les overloads inutiles.''


    Mais il faut bien que je chiffre les connexions (+hash code etc...) pour avoir un minimum de sécurité non*?

    Si je comprend bien, poll() ne demande pas le CPU pour scruter*?

    Merci pour vos réponses, je dois juste rechercher les différences TCP/UDP et je pense pouvoir commencer à coder^^

    EDIT : c'est bon j'ai trouvé la différence

    EDIT2 : le processus fils copie l'environnement du père.
    Les pointeurs pointent donc vers la même zone non?
    J'ai juste à allouer une zone mémoire et à mettre en place un mutex?

  8. #8
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par Neckara Voir le message
    1) Pour vérifier qu'un serveur est en ligne, je peux établir une socket toutes les minutes pour chaque client (sans qu'ils se soient connectés), mais n'y a-t-il pas de méthodes moins coûteux?
    Beaucoup moins couteux, mais plus complexe : tu envoies le second paquet d'echange d'authentification. Si un logiciel ecoute sur le port auquel tu t'adresses, il devrait te renvoyer un paquet contenant un message disant qu'il n'a pas recu le premier paquet.

    Avantage : c'est transparent pour l'applicatif distant, ce sera gere par la carte reseau.
    Inconvenient : necessite de solides bases en reseau, et le droit d'emettre des paquets que tu forges a la main.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  9. #9
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Je ne suis malheureusement pas très doué en réseaux...

    Sinon, j'ai regarder un peu les MUTEX, mais les seuls que j'ai trouvé sont plus adaptés à des mono-processeurs mono-tâches...

    Est-ce que vous pourriez m'indiquer des pistes?

    Je vois comment faire pour éviter de lire pendant une modification.
    Mais je ne vois pas comment éviter les modifications simultanées.

  10. #10
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    J'ai presque fini, merci pour vos conseils.

    Il ne me reste plus que deux petits problèmes :
    - Je n'arrive pas à trouver comment changer le port d'un socket.
    En effet, j'accepte le socket du client mais il faut ensuite que le serveur et le client discutent sur un port qui leur est réservé.
    Je ne vois pas trop comment les faire changer de port...

    - Si on envoi un paquet en boucle, ma connexion en ssh plante comme lors d'un fork, existe-t-il un moyen de remédier à ce problème?

Discussions similaires

  1. Livre Blanc : « 10 Questions Clés sur la Gestion Des Processus Métier »
    Par Gordon Fowler dans le forum Forum général Solutions d'entreprise
    Réponses: 0
    Dernier message: 06/02/2013, 14h38
  2. Réponses: 4
    Dernier message: 13/09/2006, 16h53
  3. question sur la gestion des css
    Par boustor dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 31/07/2006, 16h57
  4. Quelques questions sur la gestion des droits
    Par sylsau dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 04/03/2006, 14h11
  5. Question sur la gestion des fenetres MDI
    Par RémiONERA dans le forum C++Builder
    Réponses: 6
    Dernier message: 06/07/2005, 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