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 :

C++11 socket multithreaded


Sujet :

C++

  1. #1
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 19
    Points : 9
    Points
    9
    Par défaut C++11 socket multithreaded
    Bonjour,

    j'apprend actuellement le C++ afin d'accélérer quelques programmes sur mon serveur, et pour cela, j'ai décidé de réaliser un serveur HTTP multi-clients.

    Je ne veux pas utiliser de librairies telles que boost, je préfère tout re-coder moi-même afin de vraiment tout comprendre.

    Mais, je débute et rencontre déjà des problèmes Si je suis correct, pour réaliser un serveur HTTP, je dois gérer manuellement les sessions TCP, pour cela mon programme débute par une classe TCP_Server.

    Voici le code que j'ai déjà écrit pour cette classe, tout a l'air de fonctionner pour le moment.

    Header file:
    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
     
    #include <iostream>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <thread>
     
    class TCP_Server {
    public:
        // Constructor
        TCP_Server();
    private:
        // Socket descriptor
        int m_socket_desc;
        // 
        struct sockaddr_in m_server;
    };
    Source file:
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    #include "TCP_Server.h"
     
    TCP_Server::TCP_Server() {
        // Creating a socket
        m_socket_desc = socket(AF_INET, SOCK_STREAM, 0);
        if (m_socket_desc == -1) {
            std::cout << "Could not create socket" << std::endl;
        }
        else
        {
            std::cout << "Server started" << std::endl;
        }
     
        // Prepare the sockaddr_in structure
        m_server.sin_family = AF_INET;
        m_server.sin_addr.s_addr = INADDR_ANY;
        m_server.sin_port = 80;
     
        // Bind it
        // bind() return 0 when there is no problem
        if (bind(m_socket_desc, (struct sockaddr*)&m_server, sizeof(m_server)) != 0) {
            std::cout << "Bind failed" << std::endl;
        }
        else
        {
            std::cout << "Socket binded on port " << m_server.sin_port << std::endl;
        }
     
        // Put the server on (with a pending queue of 15)
        // listen() is a command used for listening to TCP handshake requests
        // listen() return 0 when there is no problem
        if (listen(m_socket_desc, 15) != 0) {
            std::cout << "Listen failed" << std::endl;
        }
        else
        {
            std::cout << "Server started" << std::endl;
        }
     
        // Create a new thread for each new TCP session when a SYN request has been detected
        while (1) {
            std::cout << "Waiting for connections ..." << std::endl;
            // std::thread thread...
        }
    }
    Si j'ai bien compris, je dois maintenant créer un nouveau thread pour chaque session TCP, lançant la méthode accept() qui va effectuer le TCP handshake ... Mais après avoir lu des dizaines de tutos en C et C++, je n'y arrive pas

    Donc je me permet de demander un petit coup de pouce de votre part

    Pour info, je code pour les plateformes debian / centOS / OSX.

  2. #2
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Bonjour

    Si tu utilises l'API du noyau Linux, c'est plus "classique" d'utiliser un fd_set pour gérer plusieurs connexions.
    http://linux.die.net/man/3/fd_set

    Je te laisse chercher des tutos avec les mots clefs fd_set et TCP.

  3. #3
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    d'accord, merci, je vais m'intéresser à cette fonction

  4. #4
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Sur plusieurs sites et forums j'ai pu lire qu'une gestion 1 connexion => 1 thread consommait trop de resources, est-ce qu'il y aurait une meilleure méthode à conseiller ?

  5. #5
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Pour ma part, je conseillerais plutôt l'usage de epoll pour gérer tes connexions plutôt que de fd_set. Cette fonction est plus puissante et supporte un très grand nombre de file descriptors, ce qui n'est pas le cas de select et de pselect qui sont limités. epoll est le remplaçant nouvelle génération de poll qui est aussi scalable mais dont les performances deviennent mauvaises si le nombre de FDs est grand.

    Pour utiliser un nombre de thread limité avec un grand nombre de connexions, il te "suffit" de surveiller plusieurs connexions dans un seul thread avec epoll.
    Find me on github

  6. #6
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Après avoir lu pas mal de doc, j'ai choisi de me tourner vers kqueue() au lieu de epoll() (je l'implémenterais peut-être plus tard pour prendre en charge plus de systèmes).

    Pour le moment, j'ai donc déclaré dans le .h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private:
        // Sockets events queue
        int socketEvents;
    Et je l'ai implémenté comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Create the events queue
    // kqueue() return -1 when there is an error
    socketEvents = kqueue();
    if (socketEvents < 0) {
        std::cout << "Socket events queue creation failed" << std::endl;
        exit(EXIT_FAILURE);
    }
    else
    {
        std::cout << "Socket events queue created" << std::endl;
    }
    Par la suite, si je comprends bien, il me faudra créer un boucle infinie "while(1){}" et enregistrer chaque nouvelle connexion dans ma queue socketEvents, est-ce correct ?
    Je me demande aussi, comment fait-on pour reconnaître quelle connexion appartient à quel client ?

  7. #7
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par elmago Voir le message
    je l'implémenterais peut-être plus tard pour prendre en charge plus de systèmes).
    Dans ce cas, autant utiliser directement libevent qui réalise déjà cette abstraction.
    Find me on github

  8. #8
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Je ne veux pas utiliser de librairies telles que boost, je préfère tout re-coder moi-même afin de vraiment tout comprendre.
    Bonjour, je veux modéliser la trajectoire dune balle de tennis que je lance à la main mais je veux commencer par étudier la théorie quantique des champs pour bien comprendre ce qui se passe au niveau du noyau....


    Ce que je veux illustrer, c'est que quand on débute, on a en général 2 objectifs antagonistes :
    • soit on veut réaliser un programme précis et donc on se tourne vers des bibliothèques haut niveau pour se faciliter la vie et arriver au résultat final.
    • soit on veut comprendre comment les technos marchent et donc on recode des applications jouets à partir de rien.


    Mais vouloir réaliser une véritable application en partant de rien, c'est aller droit dans le mur sur les 2 plans. Et vu ta première phrase, tu sembles être dans le cas 1.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  9. #9
    Membre habitué Avatar de linke
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2012
    Messages : 119
    Points : 139
    Points
    139
    Par défaut
    franchement tu te casse trop la tete pour rien, et ta pas fini de galerer.
    utiliser les threads est un vrai casse tete (synchronisation, communication entre thread, pile......)
    utilise plutot un framework, comme Qt par exemple

  10. #10
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 19
    Points : 9
    Points
    9
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message

    Ce que je veux illustrer, c'est que quand on débute, on a en général 2 objectifs antagonistes :
    • soit on veut réaliser un programme précis et donc on se tourne vers des bibliothèques haut niveau pour se faciliter la vie et arriver au résultat final.
    • soit on veut comprendre comment les technos marchent et donc on recode des applications jouets à partir de rien.


    Mais vouloir réaliser une véritable application en partant de rien, c'est aller droit dans le mur sur les 2 plans
    Je sais bien, d'où l'intérêt de vouloir apprendre ! Je ne me lance pas à corps perdu dans la création d'une application complète sans réflexion, le serveur HTTP est seulement un but final que je me suis fixé, et que je compte bien atteindre étapes par étapes ... Mon travail actuel sur les sockets consiste en la création d'un simple serveur TCP qui répondra dans un premier temps à des requêtes simples (telnet, nc, affichage des requests du navigateur côté serveur).

    C'est simplement un projet personnel sur mon temps libre, une envie de comprendre en profondeur le fonctionnement des technologies, et pas juste utiliser du gros code déjà écrit, très compliqué à comprendre en le lisant, d'où mes tentatives d'interagir avec le système directement ... Cela m'étonnerai d'ailleurs fortement que ce soit aussi compliqué que le théorie quantique, puisque Unix fournit des outils (les events manager dans mon cas) pour ces interactions, je ne re-code donc pas tout en assembleur mais essaye juste d'apprendre Unix C++ en profondeur

  11. #11
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Je connais mal kqueue, mais il me semble que epoll est plutôt plus simple à utiliser. Comme tu es dans une optique d’apprentissage, ça me semble peut-être plus pertinent de commencer par cette solution (quitte, ensuite, à regarder du côté de kqueue si ça t’intéresse).

  12. #12
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par elmago Voir le message
    Sur plusieurs sites et forums j'ai pu lire qu'une gestion 1 connexion => 1 thread consommait trop de resources, est-ce qu'il y aurait une meilleure méthode à conseiller ?
    Je confirme que ça pose problème. Si tu as 10000 connexions sur ton serveur, tu va le mettre à genoux rien que pour traiter les switch de contexte - alors que ta bande passante sera peut-être à peine entamée.

    Ce que tu essaie de faire, c'est de trouver une solution à un problème connu : le problème des (justement) 10000 connexions - C10K pour les amis de la famille (http://en.wikipedia.org/wiki/C10k_problem). Ce site (http://www.kegel.com/c10k.html) est assez complet dans la liste des solutions proposées. L'échelle suivante - C10M - recelle aussi des idées intéressantes (http://highscalability.com/blog/2013...-kernel-i.html).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

Discussions similaires

  1. [Socket] Multithreaded Server
    Par cyrill.gremaud dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 10/06/2011, 09h06
  2. socket multiThread serveur JAVA / client FLEX
    Par aliong dans le forum Flex
    Réponses: 2
    Dernier message: 28/08/2009, 20h06
  3. Socket multithread & select
    Par crealinks dans le forum Réseau
    Réponses: 3
    Dernier message: 22/11/2006, 21h36
  4. UDP/TCP multithreading/sockets asynchrones
    Par narkotik dans le forum C++
    Réponses: 4
    Dernier message: 25/07/2006, 11h35
  5. bloquage socket multithread
    Par aderick dans le forum Développement
    Réponses: 1
    Dernier message: 02/12/2004, 10h10

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