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 :

limitation connexion serveur linux


Sujet :

Réseau C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 4
    Par défaut limitation connexion serveur linux
    Bonjour,

    Après avoir lu le manuel, les différents sujets du forum et fait pas mal de tests, je souhaiterais avoir des explications au sujet du fonctionnement du listen d'un serveur de socket.
    J'ai développé un serveur en C sous linux pour mon entreprise (communication GPRS mais cela ne diffère en rien...).
    Je crée une socket sur laquelle viennent se connecter plusieurs clients, et à chaque connexion je crée un thread que je détache.
    Je souhaite pouvoir limiter le nombre de connexion à mon serveur afin de ne pas le faire mouliner pour rien (je ne suis pas le seul à fontionner sur la machine...).
    Au départ, je pensais que la valeur backlog du listen (définition : Longueur de la file d'attente par socket des connexions. Dans Linux 2.2, la valeur indiquée dans listen(2) ne correspond qu'à la longueur de la file des sockets déjà établies.) me permettait de bloquer toute nouvelle connexion une fois la limite atteinte (je supposais que linux refusait de lui même les connexions ou alors que l'accept me renvoyait -1) mais ça n'est pas le cas.
    Une fois la socket définie et établie, je fais un select en écoute sur la socket. Dans le cas où j'atteind la limite, le select m'indique toujours que des clients se connectent et l'accept fonctionne aussi donc pas de limitation sauf par mon tableau de thread qui est limité.
    Le souci est donc que les connexions à la socket sont acceptées et que même si le client n'est plus connecté, l'accept me fournit le prochain client de la file (connecté ou non avec les datas envoyées) et cela crash dans le cas d'un client non connecté.

    Pour des raisons de confidentialité, je ne peux vous fournir tout le code mais une partie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     - socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)            => création de la socket
     - fcntl(skt_fd,F_SETFL,O_NONBLOCK)                     => socket non bloquante 
     - bind                                                 => assignation d'un nom à la socket 
     - listen(skt_fd, 20)                                   => désir d'accépter des connexions 
     - while(1)
         - select(srv_fd+1, &rfds, NULL, NULL, &timeout)    => attente de réception
             - fd = accept                                  => acceptation de la connexion 
                 - si trop de client : close fd 
                 - sinon : - pthread_create                 => création du thread 
                           - pthread_detach
    Dans ce cas là, cela fonctionne et je gère moi même la limitation en closant les nouvelles connexions. Mais le problème est que dans le cas où je limite, l'accept se fait et je close donc le client émet quand même (coût de communication inutiles).
    Donc est il possible que linux fasse la limitation tout seul ? (je préfèrerais ne pas utiliser la fonction sysctl pour modifier le paramêtre tcp_max_syn_backlog qui limite la file des sockets pas encore établies ).

    Merci.

    En espèrant avoir été assez clair...

    Yannick.

  2. #2
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Ton algo est un peu compliqué pour rien...

    Modifie ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     - socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)            => création de la socket
     - fcntl(skt_fd,F_SETFL,O_NONBLOCK)                     => socket non bloquante 
     - bind                                                 => assignation d'un nom à la socket 
     - listen(skt_fd, 20)                                   => désir d'accépter des connexions 
     - while(1)
         - select(srv_fd+1, &rfds, NULL, NULL, &timeout)    => attente de réception
             - fd = accept                                  => acceptation de la connexion 
                 - si trop de client : close fd 
                 - sinon : - pthread_create                 => création du thread 
                           - pthread_detach
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     - socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)            => création de la socket
     - fcntl(skt_fd,F_SETFL,O_NONBLOCK)                     => socket non bloquante 
     - bind                                                 => assignation d'un nom à la socket 
     - listen(skt_fd, 20)                                   => désir d'accépter des connexions 
     - while(1)
         - si trop de client : 
                 Attendre
         - sinon
            - select(srv_fd+1, &rfds, NULL, NULL, &timeout)    => attente de réception
               - fd = accept                                  => acceptation de la connexion 
               - pthread_create                 => création du thread 
               - pthread_detach
    Bien sûr il te faut un moyen pour savoir quand un client a terminé...

    Ceci te permet de garder le client en attente sans l'accepter pour rien
    Jc

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 4
    Par défaut
    Merci pour ta réponse.
    Il est vrai que cela peut être une bonne solution.
    Mais une chose que j'ai oublié de préciser est que lorsque le timeout du select le fait sortir (retour à 0), je vérifie depuis combien de temps mes threads existent et les kills en conséquence (ça ne devrait pas arriver mais c'est une protection supplémentaire).
    De plus, les clients ont des timeout eux aussi, s'ils n'ont rien reçu du serveur avant 30s, il se déconnecte.
    Donc si je reste en attente et que le select me fournit la prochaine connexion de la file d'attente qui est déconnectée, ça crash (c'est pour cela que je faisait l'accept puis le close direct pour éviter ça mais le problème c'est que le produit émet pour rien et cela coûte en communication gprs).
    Pour savoir quand le client à terminer, je fais ça dans le thread donc pas de souci de ce côté là.
    Peut être que je souhaite avoir une solution idéale qui n'existe pas...que le listen bloque lui même les connexions en trop...

  4. #4
    Membre Expert
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Par défaut
    Au lieu de créer des threads à chaque fois, pourquoi ne pas tout traiter dans le même thread ?


    Dans un thread tu fais un listen.

    Dans un autre thread, tu t'occupes de gérer le tout avec select et des ensembles MAN Select Cela fonctionne très bien chez moi et je fais l'économie de lancer des thread.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 4
    Par défaut
    Merci.
    Je vois à peu près ta solution (corriges moi si je me trompes) :
    - je lance un thread dans lequel je fais un listen et un accept bloquant,
    je mets dans un tableau global les sockets (fd) générées par l'accept
    - dans un autre thread, je fais un select sur les fd du tableau global.
    En cas de réception, je lance ma fonction de traitement.
    Mais j'ai peur que ça n'enlève pas le problème des "connexions de la file d'attente déconnectée"...

  6. #6
    Membre Expert
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Par défaut
    Attention à la limitation par les ensembles qui est contournable, mais ne pas les utiliser tel quel.

    L'idée est la et cela te permet de traiter plus vite les données donc de gagner en clients potentiels.

    A la place des tableaux, il serait mieux de mettre en place une liste simple/doublement chaîné.

    (je n'ai jamais testé), mais la limitation de (si je ne dis pas trop de bêtise) la taille réservé pour le nombre de messages dans la file d'attente sous Windows je crois que c'est 5, sous Linux aucune idée .

    Mais logiquement, si un socket s'ouvre sur le serveur et que le serveur est TRES occupé, le timeout du socket indique qu'il n'a pas réussit à joindre le serveur.

    Tu peux fixer une limitation à 50 utilisateurs par exemple.

    Algo

    Si >50 utilisateurs

    alors le thread "un listen et un accept bloquant" se met en pausee (si c'est possible, car les pauses de thread -> :-/) sinon un petit test et tu fais du sleep tant que le nombre d'utilisateur dans l'autres thread n'est pas redescendu en dessous de 50.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 4
    Par défaut
    Merci pour la réponse...
    A bientôt.

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

Discussions similaires

  1. Limite performances serveur Linux/Postgresql
    Par jinpol dans le forum Administration
    Réponses: 17
    Dernier message: 07/11/2008, 12h22
  2. Connexion entre serveur Linux et Client Windows
    Par MarocWare dans le forum Réseau
    Réponses: 6
    Dernier message: 07/12/2007, 20h28
  3. serveur tchat C++(multi connexion) UNIX!!! linux
    Par karadoc74 dans le forum Linux
    Réponses: 2
    Dernier message: 14/06/2007, 11h30
  4. délai de connexion client linux, serveur windows
    Par cadbury dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 27/11/2006, 16h05

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