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

Python Discussion :

serveur avec plusieurs clients Socket et select


Sujet :

Python

  1. #1
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2015
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2015
    Messages : 35
    Par défaut serveur avec plusieurs clients Socket et select
    Bonjour,

    J'ai un serveur avec plusieurs clients que je traite avec le module select.

    Je voudrais que à chaque fois qu'un client envoie une information, le serveur récupère l'information (ce qui marche avec mon serveur ) et renvoie un message a tous les clients (c'est moins bien ).
    J'essaye d'utiliser select mais le resultat n'est pas celui escompté !, je voudrais transmettre un message unique a tous les clients connectes à chaque envoi d'information par un client.

    Je ne comprends pas trop mon erreur et comment bien utiliser select.
    Merci de votre aide



    le code de mon serveur est
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    #! /usr/bin/env python
    # -*- coding:Utf8 -*-
     
     
     
    import socket
    import select
     
    hote = ''
    port = 12800
     
    connexion_principale = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connexion_principale.bind((hote, port))
    connexion_principale.listen(5)
    print("Le serveur écoute à présent sur le port {}".format(port))
     
    serveur_lance = True
    clients_connectes = []
    while serveur_lance:
        # On va vérifier que de nouveaux clients ne demandent pas à se connecter
        # Pour cela, on écoute la connexion_principale en lecture
        # On attend maximum 50ms
        connexions_demandees, wlist, xlist = select.select([connexion_principale],
            [], [], 0.05)
     
        for connexion in connexions_demandees:
            connexion_avec_client, infos_connexion = connexion.accept()
            # On ajoute le socket connecté à la liste des clients
            clients_connectes.append(connexion_avec_client)
     
        # Maintenant, on écoute la liste des clients connectés
        # Les clients renvoyés par select sont ceux devant être lus (recv)
        # On attend là encore 50ms maximum
        # On enferme l'appel à select.select dans un bloc try
        # En effet, si la liste de clients connectés est vide, une exception
        # Peut être levée
        clients_a_lire = []
        clients_a_informer = []
     
        try:
            clients_a_lire, clients_a_informer, xlist = select.select(clients_connectes,clients_connectes, [], 0.01)
        except select.error:
            pass
        else:
            # On parcourt la liste des clients à lire
            for client in clients_a_lire:
                client.send(b"Bien recu")
                # Client est de type socket
                msg_recu = client.recv(1024)
                # Peut planter si le message contient des caractères spéciaux
                msg_recu = msg_recu.decode()
                print("Reçu {}".format(msg_recu))
     
     
                if msg_recu == "fin":
                    serveur_lance = False
     
            for client in clients_a_informer: 
                message="bonjour a tous  \n"
                message=message.encode("Utf8")
                client.send(message)
     
     
     
     
    print("Fermeture des connexions")
    for client in clients_connectes:
        client.close()
     
    connexion_principale.close()
    le code du client basique que j'utilise est

    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
    #! /usr/bin/env python
    # -*- coding:Utf8 -*-
     
     
    import socket
     
    hote = "localhost"
    port = 12800
     
    connexion_avec_serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connexion_avec_serveur.connect((hote, port))
    print("Connexion établie avec le serveur sur le port {}".format(port))
     
    msg_a_envoyer = b""
    while msg_a_envoyer != b"fin":
        msg_a_envoyer = input("> ")
     
        msg_a_envoyer = msg_a_envoyer.encode("Utf8")
     
        connexion_avec_serveur.send(msg_a_envoyer)
        msg_recu = connexion_avec_serveur.recv(1024)
        print(msg_recu.decode("Utf8")) 
     
     
    print("Fermeture de la connexion")
    connexion_avec_serveur.close()

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 030
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 030
    Par défaut
    Je voudrais que à chaque fois qu'un client envoie une information, le serveur récupère l'information (ce qui marche avec mon serveur ) et renvoie un message a tous les clients (c'est moins bien ).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for client in clients:
        client.sendall(data) # data est le résultat de la méthode recv
    Mais avant tu dois créer une liste des clients qui se connectent, c'est la variable clients ci-dessus.

    EDIT: Tu peux te renseigner sur asyncio si beaucoup de clients.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 795
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par flyingfr Voir le message
    Je ne comprends pas trop mon erreur et comment bien utiliser select.
    Je ne connais pas trop les sockets en Python mais je les connais bien en C donc j'arrive à peu près à comprendre ce que tu fais.

    Il me semble que ici ...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    try:
        clients_a_lire, clients_a_informer, xlist = select.select(clients_connectes,clients_connectes, [], 0.01)
    except select.error:
        pass
    ... il y a un truc à rectifier. Car là, tu masques défintivement toute erreur du select. Or justement ton souci étant son utilisation, tu devrais ici, en cas d'erreur, regarder ce qui se passe et non la masquer. Peut-être de cette façon
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    try:
        clients_a_lire, clients_a_informer, xlist = select.select(clients_connectes,clients_connectes, [], 0.01)
    except select.error, e:
        print("Erreur select - %s", e)

    Et ensuite, tu devrais afficher le contenu de "client_a_lire" et "client_a_informer" vérifier si ces variables sont bien renseignées correctement...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2015
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2015
    Messages : 35
    Par défaut
    Bonjour,

    Merci de ta reponse mais je ne crois pas que ça solutionne mon problème.
    J'ai testé mais sans succès car si j'ai bien compris cette méthode continue d’envoyer des données d’une chaîne jusqu’à ce que toutes les données aient été envoyées ou qu’une erreur se produise. ce n'est pas vraiment mon problème, les données partent bien vers le client.

  5. #5
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2015
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2015
    Messages : 35
    Par défaut
    @ servr

    Bonjour,
    Merci de te pencher sur ma question.
    Il y a bien une erreur générée dans try s'il n'y a pas de client connecté, mais cette erreur disparaît au premier client connecté et ce fonctionnement n'est pas anormal.
    Par contre en fait je pense que je n'arrive pas a récupérer la liste des connexions clients correctement,



    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
    serveur_lance = True
    clients_connectes = []
    while serveur_lance:
        # On va vérifier que de nouveaux clients ne demandent pas à se connecter
        # Pour cela, on écoute la connexion_principale en lecture
        # On attend maximum 50ms
        connexions_demandees, wlist, xlist = select.select([connexion_principale],
            [], [], 0.05)
     
        for connexion in connexions_demandees:
            connexion_avec_client, infos_connexion = connexion.accept()
            # On ajoute le socket connecté à la liste des clients
            clients_connectes.append(connexion_avec_client)
     
        # Maintenant, on écoute la liste des clients connectés
        # Les clients renvoyés par select sont ceux devant être lus (recv)
        # On attend là encore 50ms maximum
        # On enferme l'appel à select.select dans un bloc try
        # En effet, si la liste de clients connectés est vide, une exception
        # Peut être levée
        clients_a_lire = []
        try:
            clients_a_lire, wlist, xlist = select.select(clients_connectes,
                    [], [], 0.05)
        except select.error:
            pass
        else:
            # On parcourt la liste des clients à lire
            for client in clients_a_lire:
                # Client est de type socket
                msg_recu = client.recv(1024)
                # Peut planter si le message contient des caractères spéciaux
                msg_recu = msg_recu.decode()
                print("Reçu {}".format(msg_recu))
                client.send(b"5 / 5")
                if msg_recu == "fin":
                    serveur_lance = False
     
        print (clients_connectes )               
        for client in clients_connectes :
            client.send(b"essai\n")
    le print (clients_connectes ) donne en boucle
    [<socket.socket fd=692, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 12800), raddr=('127.0.0.1', 50994)>, <socket.socket fd=648, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 12800), raddr=('127.0.0.1', 50998)>]


    il y a manifestement une erreur, je n'envoie le message qu'au client initial et en boucle !

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 672
    Par défaut
    Salut,

    Citation Envoyé par flyingfr Voir le message
    il y a manifestement une erreur, je n'envoie le message qu'au client initial et en boucle !
    Et si vous ajoutiez un print "dans" la boucle pour vous assurez que ce n'est pas le cas?

    Et lorsque vous serez convaincu que le message est expédié, peut être faudra-t-il regarder ce qu'il se passe côté client.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2015
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2015
    Messages : 35
    Par défaut
    @wiztricks

    Très bonne remarque !
    J'ai essayé de mettre un print dans la boucle visiblement j'envoie a tous mes clients qui bien sur sont bloques en attente d’émission ! et ne peuvent pas recevoir, il faut que je modifie le client.
    J'ai essayé avec connexion.setblocking(0) ça a l'ai de poser d'autres problèmes mais je pense que c'est la bonne voie .
    Merci.

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 795
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par flyingfr Voir le message
    Il y a bien une erreur générée dans try s'il n'y a pas de client connecté, mais cette erreur disparaît au premier client connecté
    Pas chez-moi. Chez-moi, il se lance et se met en attente gentiment sans souci.

    En revanche, j'ai rajouté un print(client) dans ta boucle d'écriture "Bonjour à tous". Et je remarque que cette boucle s'exécute dès qu'un client se connecte. Or, elle ne devrait s'exécuter qu'à réception d'un message. Donc là déjà il y a un souci. On dirait que ton serveur n'attend pas d'avoir lu sur le client.recv() pour continuer. Si j'étais en C, j'irais voir du côté d'un flag NOWAIT à activer (ou plutôt ici désactiver)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 672
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 672
    Par défaut
    Citation Envoyé par flyingfr Voir le message
    et ne peuvent pas recevoir, il faut que je modifie le client.
    voilà.
    Dans la pratique, il faudrait aussi, côté client, un select qui regarde si l'utilisateur à tapé un caractère sur le clavier ou s'il y a un message à lire côté réseau.... Mais si vous êtes sous Windows, select n'est supporté que pour les sockets (réseau) pas facile de vous en sortir sans utiliser des threads: la thread principale dialogue avec l'utilisateur (le clavier) une autre thread pour la réception des messages réseau.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Janvier 2015
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2015
    Messages : 35
    Par défaut
    Bonjour,
    Je vais effectivement passer par des threads sur le client.
    Merci à tous pour vos conseils.

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

Discussions similaires

  1. Plusieurs client Socket sur la même serveur
    Par Jeams dans le forum NetBeans
    Réponses: 0
    Dernier message: 27/02/2011, 21h19
  2. Pousser des donnees depuis le serveur vers plusieurs clients avec WCF
    Par NoussaL dans le forum Windows Communication Foundation
    Réponses: 6
    Dernier message: 30/09/2008, 17h11
  3. serveur et plusieurs client
    Par asma nafti dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 29/05/2007, 11h26
  4. Comment faire un serveur hébergeant plusieurs client simultanée
    Par Alexlesilex dans le forum Développement
    Réponses: 15
    Dernier message: 01/03/2007, 14h15
  5. un Tserversocket pour plusieurs clients socket?
    Par andyafrique dans le forum C++Builder
    Réponses: 2
    Dernier message: 05/10/2006, 21h02

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