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/Web Python Discussion :

Création serveur,multi thread, multi ports


Sujet :

Réseau/Web Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut Création serveur,multi thread, multi ports
    Bonjour à tous,

    J'ai joué avec pas mal de petits morceaux de code, trouvés de ci de là, pour créer une connexion socket. Toutefois je n'ai pas trouvé de programmes qui ressembleraient fortement à ce que j'ai besoin.
    Je vous explique ce que je désire faire avec certains impératifs dont je ne suis pas maitre.

    J'ai besoin d'un serveur qui puisse être connectés par 4 et seulement 4 clients sur 4 ports différents (10001 à 10004 obligatoire)
    Chaque client peut envoyer, à n'importe quel moment, une commande, sur une dizaine de caractères ASCII maxi terminé par le caractère spécial $10 (LF)

    Le serveur doit pouvoir recevoir cet ordre ou commande, et parfois, il réponds au client qui à lancé la requête et/ou execute l'ordre donné après l'avoir analysé.

    Je suppose que le serveur doit utiliser les threads ? C'est une chose que je ne pige pas trop.
    Si je comprends le thread, c'est une manière de faire travailler mes connexions en parallèle (4 threads pour 4 ports) avec mon prog principal qui:
    1: surveille si quelque chose est arrivé d'un socket
    2: execute les ordres
    Sans perturber/retarder ce qu'il peut faire éventuellement d'autre.
    C'est bien cela ?

    Je peux récupérer facilement sous forme de string par exemple, chaque réception ?

    Maintenant si plusieurs ordres arrivent en même temps de mes différents clients que se passe-t-il ?
    Vais-je en zapper ?
    Risquent-ils d'être altérés ?
    Je précise que chaque client envoie beaucoup d'ordres. Avec la latence d'un réseau cela peut être de l'ordre d'un ordre toutes les 100mSec, et que chaque client n'est forcément pas synchrone, cela peut faire beaucoup de choses à traiter.

    J'ai besoin aussi de savoir si une connexion s'est arrêtée (client deconnecté)

    Voilà, c'est pas quelque chose de commun semble-t-il puisque je n'ai pas trouvé de bout de codes qui y ressemblerait. Enfin je dis cela, c'est surtout, parce que je ne sais par quel exemple commencer, étudier, dégrossir et poser des questions pour apprendre, comprendre et me corriger. (et m'en souvenir, car j'ai ma ram perso qui oublie vite )

    Toute aide bienvenue

  2. #2
    Membre averti
    Homme Profil pro
    Développeur en formation
    Inscrit en
    Juillet 2013
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en formation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2013
    Messages : 300
    Points : 413
    Points
    413
    Par défaut
    Le but est de lancer 4 threads : un par client. Chacun écoute les données et agît en conséquence. J'imagine que la réaction va être la même pour chaque client pour une même requête donc il faut créer une classe qui hérite de Thread :
    (je n'ai pas étoffé, on peut rajouter des trucs, des try...)
    côté serveur, ça donne :
    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
     
    import threading
    import socket
     
    class Client(threading.Thread):
        def __init__(self, conn):
    	threading.Thread.__init__(self)
    	self.connexion = conn		   # socket de connexion
     
        def run(self):
    	global truc #si tu as des variables globales à utiliser
    	while True :#j'imagine qu'on est à l'écoute en permanence
                commande=self.connexion.recv(1024)
                #ce qui tu as à faire avec cette commande
                self.connexion.send(b"la commande a bien été exécutée")#le rendu, ça va simplifier les choses de toujours faire ça, on peut évidemment mettre un autre message
     
    #pour l'établissement des connexions, j'imagine que tu sais comment faire
     
    thr_client1=Client(connexion_1)
    thr_client2=Client(connexion_2)
    thr_client3=Client(connexion_3)
    thr_client4=Client(connexion_4)
    thr_client1.start()
    thr_client2.start()
    thr_client3.start()
    thr_client4.start()
    Du côté du client, pas besoin de thread, juste un truc (je simplifie) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while True :
        connexion.send(input("Entrez la commande : ").encode())
        print(connexion.recv().decode())
    Voilà, ça devrait être bon.
    Bouddha : Tout n'est qu'illusion en ce bas monde.
    Jésus : Tout est amour divin.
    Einstein : Tout est relatif dans cet espace-temps.
    Moi : Tout est binaire sur ce forum.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Citation Envoyé par hherve Voir le message
    Je suppose que le serveur doit utiliser les threads ? C'est une chose que je ne pige pas trop.
    Si je comprends le thread, c'est une manière de faire travailler mes connexions en parallèle (4 threads pour 4 ports) avec mon prog principal qui:
    1: surveille si quelque chose est arrivé d'un socket
    2: execute les ordres
    Sans perturber/retarder ce qu'il peut faire éventuellement d'autre.
    C'est bien cela ?
    Le serveur ne doit pas nécessairement utiliser les threads et les serveurs normaux évitent de les utiliser.
    Un serveur "normal" devant être capable de gérer un maximum de client, il devra utiliser un minimum de ressources ce qui est incompatible avec 1 client = 1 thread.

    Si vous avez 4 clients "au plus", utiliser 1 thread par client sera une simplification intéressante de votre code.

    Je peux récupérer facilement sous forme de string par exemple, chaque réception ?
    Vous utiliserez à priori TCP/IP.
    client et serveur vont s'échanger des streams de bytes.
    En Python, bytes et str sont de nature différentes.

    Maintenant si plusieurs ordres arrivent en même temps de mes différents clients que se passe-t-il ?
    Vais-je en zapper ?
    Risquent-ils d'être altérés ?
    Je précise que chaque client envoie beaucoup d'ordres. Avec la latence d'un réseau cela peut être de l'ordre d'un ordre toutes les 100mSec, et que chaque client n'est forcément pas synchrone, cela peut faire beaucoup de choses à traiter.
    TCP/IP vous garantit que les bytes écrits seront acheminés et reçus dans l'ordre. S'il y a un problème client et serveur çà va remonter une erreur que le code devra gérer.


    Voilà, c'est pas quelque chose de commun semble-t-il puisque je n'ai pas trouvé de bout de codes qui y ressemblerait. Enfin je dis cela, c'est surtout, parce que je ne sais par quel exemple commencer, étudier, dégrossir et poser des questions pour apprendre, comprendre et me corriger. (et m'en souvenir, car j'ai ma ram perso qui oublie vite )
    Je vous recommande la lecture et la pratique d'un tuto.
    Nous faisons ici beaucoup de publicité pour le Swinnen.
    Si vous voulez voir à quoi ressemble ce que vous voulez faire, vous pouvez lire le ch20.
    Si c'est "indigeste", c'est probablement qu'il vous faudra lire les chapitres précédents.

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

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je me suis un peu amusé avec ce genre de serveur il y a quelques années, et j'en ai gardé quelques codes très simples ici: http://python.jpvweb.com/mesrecettes...eur_tcp_stream.

    Ils fonctionnent avec TCP/IP, mais ce n'est pas du web: le client est un programme spécifique, pas un navigateur.

    Il y a en particulier 2 serveurs "asynchrones", l'un utilisant les threads et l'autre les processus (chaque nouvelle requête est traitée sans attendre que la requête précédente soit terminée)

    C'est du Python 2, mais ça devrait pouvoir se convertir facilement en Python 3.

    Je viens de vérifier: ça continue à fonctionner (ça fait du calcul algébrique). Mais je n'ai jamais sollicité ces serveurs "à fond", et si tu les utilises, ça m'intéresse de savoir ce qui se passe alors.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    C'est du Python 2, mais ça devrait pouvoir se convertir facilement en Python 3.

    Je viens de vérifier: ça continue à fonctionner (ça fait du calcul algébrique). Mais je n'ai jamais sollicité ces serveurs "à fond", et si tu les utilises, ça m'intéresse de savoir ce qui se passe alors.
    Autant mentionner les exemples de la documentation Python du module socketserver.
    Ils sont à jour et bien plus complets que vos essais.

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

  6. #6
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    merci pour vos réponses.

    J'ai donc pris un exemple du chapitre 20 de Mr Swinnen, et pas de chance (copié collé ) il fonctionne quand il veut, c'est à dire qu'il me refuse presque tout le temps la connexion....

    @ Tyrtamos, je vais aller voir votre site, mais il est sûr, comme dit W, qu'il faudrait que je comprenne bien comment fonctionne les socket, et que je vais aller chercher de la doc explicite là dessus.

    Je ne sais pas si c'est parce que je ne programmais jusqu'à maintenant qu'en BASIC sur µControlleurs, mais le python me désempare (j'ai pourtant lu en entier le bouquin du SDZ)

    Bien, j'ai quand même un petit prog récupéré qui tourne en threading sur 1 seul port (donc ça ne colle pas). Si ce prog peut servir de base, sans tout chambouller, j'en serais ravi.
    Il me faut limiter le nombre de connexion par port donc je dois passer le serversock.listen(5) à serversock.listen(1)
    mais pour avoir mes 4 connexions, quand tous mes clients veulent se connecter, c'est la ligne serversock.bind(ADDR) qui contient uniquement mon port défini plus haut qui pose pb. Je peux pas mettre 4 fois cette ligne avec 4 ports différents !
    Voilà le genre de choses qui me bloquent...

    PS: J'utilise PYTHON 2.7, et pour mes tests clients le freeware PUTTY


    Merci de vos idées
    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
     
    from socket import *
    import thread
     
    BUFF = 25
    HOST = ''# must be input parameter @TODO
    PORT = 10002 # must be input parameter @TODO
    def response(key):
        return 'Server response: ' + key
     
    def handler(clientsock,addr):
        while 1:
            data = clientsock.recv(BUFF)
            if not data: break
            print repr(addr) + ' recv:' + repr(data)
            clientsock.send(response(data))
            print repr(addr) + ' sent:' + repr(response(data))
            if "close" == data.rstrip(): break # type 'close' on client console to close connection from the server side
     
        clientsock.close()
        print addr, "- closed connection" #log on console
     
    if __name__=='__main__':
        ADDR = (HOST, PORT)
        serversock = socket(AF_INET, SOCK_STREAM)
        serversock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        serversock.bind(ADDR)
        serversock.listen(5)
        while 1:
            print 'waiting for connection... listening on port', PORT
            clientsock, addr = serversock.accept()
            print '...connected from:', addr
            thread.start_new_thread(handler, (clientsock, addr))

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Prenez un truc qui (devrait) marche(r) sans threads:
    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
    from socket import *
     
    BUFF = 25
    HOST = ''# must be input parameter @TODO
    PORT = 10002 # must be input parameter @TODO
    def response(key):
        return 'Server response: ' + key
     
    def handler(clientsock,addr):
        while 1:
            data = clientsock.recv(BUFF)
            if not data: break
            print repr(addr) + ' recv:' + repr(data)
            clientsock.send(response(data))
            print repr(addr) + ' sent:' + repr(response(data))
            if "close" == data.rstrip(): break # type 'close' on client console to close connection from the server side
     
        clientsock.close()
        print addr, "- closed connection" #log on console
     
    if __name__=='__main__':
        ADDR = (HOST, PORT)
        serversock = socket(AF_INET, SOCK_STREAM)
        serversock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        serversock.bind(ADDR)
        serversock.listen(1)
        clientsock, addr = serversock.accept()
        handler (clientsock, addr)
    Transformez le en fonction:
    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
    from socket import *
    from socket import *
     
    BUFF = 25
     
    def server(host, port):
     
        def response(key):
            return 'Server response: ' + key
     
        def handler(clientsock,addr):
            while 1:
                data = clientsock.recv(BUFF)
                if not data: break
                print repr(addr) + ' recv:' + repr(data)
                clientsock.send(response(data))
                print repr(addr) + ' sent:' + repr(response(data))
                if "close" == data.rstrip(): break # type 'close' on client console to close connection from the server side
     
            clientsock.close()
            print addr, "- closed connection" #log on console
     
        addr = (host, port)
        serversock = socket(AF_INET, SOCK_STREAM)
        serversock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        serversock.bind(addr)
        serversock.listen(1)
        clientsock, addr = serversock.accept()
        handler(clientsock, addr)
     
    if __name__=='__main__':
        HOST = ...
        PORT = ...
        server(HOST, PORT)
    Puis on associe un thread par port:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if __name__=='__main__':
        import threading
        HOST = ...
        PORTS = ...
        threads = []
        for port in PORTS:
             th = threading.thread(target=server, args=(HOST, port))
             th.start()
             threads.append(th)
        ... ici on attend que ca se termine...
    L'idée d'organisation est: un serveur qui fonctionne pour un port qu'on réplique sur les N port.
    Reste à rendre çà plus robuste: çà prend plus de temps que faire des cut&paste!
    Et vous n'etes pas encore rendu ;-)

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

  8. #8
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Et vous n'etes pas encore rendu ;-)

    Là je veux bien vous croire !

    je teste un peu votre code et j'ai un msg d'erreur si vous pouviez me l'expliquer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    C:\Python27\lib\threading.pyc
     
    Traceback (most recent call last):
      File "E:/python/wiz1.py", line 40, in <module>
        th = threading.thread(target=server, args=(HOST, port))
    AttributeError: 'module' object has no attribute 'thread'
    mes essais pour trouver ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    if __name__=='__main__':
        import threading
        print threading.__file__
        HOST = ''
        PORTS = [10001,10002,10003,10004]
        threads = []
        for port in PORTS:
            th = threading.thread(target=server, args=(HOST, port))
            #target est la fonction appelée par le Thread.
            #args est un tuple d'arguments pour l'invocation de la fonction target
            th.start()
            threads.append(th)
        #... ici on bosse !... ;-)

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Ah ben oui, il faut une majuscule a Thread:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        for port in PORTS:
            th = threading.Thread(target=server, args=(HOST, port))
            #target est la fonction appelée par le Thread.
            #args est un tuple d'arguments pour l'invocation de la fonction target
            th.start()
    Avez vous pris le temps de tester le code de serveur avant?

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

  10. #10
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Ah ben oui, il faut une majuscule a Thread:

    Je faisais des recherches google sur le msg d'erreur m'induisant loin d'une majuscule !

    Avez vous pris le temps de tester le code de serveur avant?

    Non sinon j'aurais déjà vu qu'il y a un problème d'autorisation semble-t-il (?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Traceback (most recent call last):
      File "E:/python/wiz1-server.py", line 34, in <module>
        server ('127.0.0.1',10001)
      File "E:/python/wiz1-server.py", line 26, in server
        serversock.bind(addr)
      File "C:\Python27\lib\socket.py", line 224, in meth
        return getattr(self._sock,name)(*args)
    error: [Errno 10013] Une tentative d’accès à un socket de manière interdite par ses autorisations d’accès a été tentée
    Bon je vais dans le parrefeu de Win7 et autorise python.exe, mais toujours rien.
    par contre si je donne ma propre adresse IP à HOST (192.168.0.14) le programme fonctionne
    Un 1er essai qui marche.
    je ne touche à rien et relance et plus rien (sauf l'error 10013)



    Merci wiztricks

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Citation Envoyé par hherve Voir le message
    par contre si je donne ma propre adresse IP à HOST (192.168.0.14) le programme fonctionne
    Un 1er essai qui marche.
    je ne touche à rien et relance et plus rien (sauf l'error 10013)
    Essayez de changer le numéro du port si çà se reproduit.
    Internet a été construit pour survivre aux pannes en tout genre.
    Vous avez une mécanique qui interdit la réutilisation du port jusqu'à un timeout de quelques minutes.
    Cela participe à s'assurer de qui et quoi.

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

  12. #12
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Oui wiz, cela me semble juste car j'ai éteint le pc hier soir et aujourd'hui tout semble aller.

    Mais... ben oui il y a un mais, si l'un des clients se déconnecte, puis tente de se reconnecter sur son port. La connexion est refusée.
    Ce ne serait pas à cause d'une choses dont j'ai pas mal entendu parler:
    le thread qui a été ouvert resterait en quelque sorte actif car non clos ?

    je vais tenter de chercher de se côté cet aprem.
    Bonne fin de semaine !

  13. #13
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Citation Envoyé par hherve Voir le message
    Mais... ben oui il y a un mais, si l'un des clients se déconnecte, puis tente de se reconnecter sur son port. La connexion est refusée.
    Ce ne serait pas à cause d'une choses dont j'ai pas mal entendu parler:
    le thread qui a été ouvert resterait en quelque sorte actif car non clos ?

    je vais tenter de chercher de se côté cet aprem.
    Ne vous laissez pas impressionner pas les légendes urbaines.
    Relisez le code, le thread se termine après la déconnexion du client.
    A vous de le comprendre et le corriger pour qu'il attende la demande de connexion suivante.
    La question dans se cas sera de savoir comment va bien pouvoir se terminer ce foutu programme.

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

  14. #14
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    ok.. J'aime cette façon d'avancer... je reviendrais avec le résultat des réflexions/expérimentations !


    Merci
    Amicalement

  15. #15
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Oh là là,

    Je m'arrache les cheveux !

    ps: je n'ai encore rien modifié et mon appli finale devrait tourner sur un raspberry pi

    En fait ce n'est pas quelques minutes qu'il faut pour ne plus avoir de message d'erreur, mais relancer le PC (Win7 64).
    D'autres problèmes,cette fois, sous UBUNTU. Lorsque je relance le programme python il me réponds cela: ( ok après redemarrage du pc linux)


    /usr/lib/python2.7/threading.pyc
    >>> Exception in thread Thread-6:
    Traceback (most recent call last):
    File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
    File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
    File "/home/herve/Bureau/wiz1.py", line 27, in server
    serversock.bind(addr)
    File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
    error: [Errno 98] Address already in use

    Exception in thread Thread-7:
    Traceback (most recent call last):
    File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
    File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
    File "/home/herve/Bureau/wiz1.py", line 27, in server
    serversock.bind(addr)
    File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
    error: [Errno 98] Address already in use

    Exception in thread Thread-8:
    Traceback (most recent call last):
    File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
    File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
    File "/home/herve/Bureau/wiz1.py", line 27, in server
    serversock.bind(addr)
    File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
    error: [Errno 98] Address already in use
    Bref il m'ouvre d'autres threads on dirait.

    Pour ce qui est du programme en lui même et le fait qu'il n'accepte pas une nouvelle connexion du client qui s'était déconnecté. Puisque le thread est fermé,(comment je le sais ? j'en suis certain ?) il me faut pouvoir le réouvrir comme cela se passe dans la partie if __name__ =='__main__' mais peut-être que je dois en premier lieu savoir quel est le port qui était déconnecté ? Mais je vois pas trop comment faire hormis que dans la partie juste nommée la mise en route se fasse par un appel de fonction qui lancerait les threads.... le thread en question ?

    C'est pas simple....

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Salut,

    Moi je ne connais que le code que j'ai posté plus haut.
    Ca ne démarre qu'un thread par port:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        PORTS = [10001,10002,10003,10004]
        threads = []
        for port in PORTS:
            th = threading.thread(target=server, args=(HOST, port))
            #target est la fonction appelée par le Thread.
            #args est un tuple d'arguments pour l'invocation de la fonction target
            th.start()
    Après effectivement, si on essaie de démarrer plusieurs threads "serveur" sur le même port, çà va raler: "error: [Errno 98] Address already in use".
    Fort probable que cela soit du à une modif dans votre code. En tous cas, si vous ne le postez pas, pas facile de l'éliminer de la liste "usual suspects" (et on va pas se fatiguer à échafauder d'autres théories sans éliminer ceux-là d'abord).

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

  17. #17
    Nouveau Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 30
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    bonjour tout le monde j'ai besoin de faire une communication entre un serveur multithread et des clients pour qu'ils s'échangent de messages
    voila le code de serveur

    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.*;


    public class ServeurMT extends Thread{
    private int nbClient=0;

    /**
    * @param args
    */
    public void run() {
    try {
    ServerSocket ss=new ServerSocket(1973);
    while(true){
    Socket s=ss.accept();
    nbClient++;
    new ThreadClient(s,nbClient).start();

    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    public static void main(String[] args) {
    new ServeurMT().start();

    }

    }



    et c'est le code de thread

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;


    public class ThreadClient extends Thread {
    private Socket socket;
    private int numClient;

    public ThreadClient(Socket s, int nbClient) {
    this.numClient=nbClient;
    this.socket=s;
    }

    public void run(){
    try {
    BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter pw=new PrintWriter(socket.getOutputStream());
    pw.println("Vous etes le client num "+numClient);

    System.out.println("Connexion du client "+numClient);
    System.out.println(socket.getRemoteSocketAddress());
    while(true){
    String req=in.readLine();
    System.out.println(req);
    pw.println(req.length());

    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }



    et ceci pour le client

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;


    public class ThreadClient extends Thread {
    private Socket socket;
    private int numClient;

    public ThreadClient(Socket s, int nbClient) {
    this.numClient=nbClient;
    this.socket=s;
    }

    public void run(){
    try {
    BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter pw=new PrintWriter(socket.getOutputStream());
    pw.println("Vous etes le client num "+numClient);

    System.out.println("Connexion du client "+numClient);
    System.out.println(socket.getRemoteSocketAddress());
    while(true){
    String req=in.readLine();
    System.out.println(req);
    pw.println(req.length());

    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }


    à l'éxecution j 'obtiens
    serveur.PNG

    et le client n'affiche rien
    quelqu'un peut m'aider svp?

  18. #18
    Membre à l'essai
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Janvier 2005
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    @ DoussaGL
    Je crois que vous vous trompez de section !

    @ Wiz,

    Voilà ou j'en suis aujourd'hui.
    Lorsque le thread se ferme, je repère sur quel port il était et j'appelle une fonction thread_reopen que j'ai placé dans le code. Cela semble fonctionner, j'arrive quasi à chaque fois à reconnecter les clients telnet sur les ports.

    voilà le code en entier:
    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
     
    # -*- coding: cp1252 -*-
    from socket import *
    import sys
     
    def server(host, port):
        print "server function"
        def response(key):
            return 'echo: ' + key
     
        def handler(clientsock,addr):
            print " handler function"
            while 1:
                data = clientsock.recv(25) #25 bytes
                if not data: break         #out of the loop
                print repr(addr) + ' recv:' + repr(data)
                clientsock.send(response(data))
                print repr(addr) + ' sent:' + repr(response(data))
                if "close" == data.rstrip(): break # out of the loop
     
            #came out of loop
            clientsock.close()
            print addr, "- closed connection",port #log on console
            thread_reopen(port)
     
        addr = (host, port)
        #create an AF_INET, STREAM socket (TCP) nammed 'serversock'
        serversock = socket(AF_INET, SOCK_STREAM)
        #Address Family : AF_INET (this is IP version 4 or IPv4)
        #Type : SOCK_STREAM (this means connection oriented TCP protocol)
        serversock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        serversock.bind(addr)
        serversock.listen(1)
        clientsock, addr = serversock.accept() #serversock = socket(AF_INET, SOCK_STREAM)
        print "fin ",th
        handler(clientsock, addr) # loop on 'handler' function
        print "handler function end "
     
    def thread_reopen(port):
        th = threading.Thread(target=server, args=(HOST, port))
        th.start()
        threads.append(th)
        print th,port
     
     
     
    if __name__=='__main__':
        import threading
        print "name"
        serversock = socket(AF_INET, SOCK_STREAM)
        HOST = '' # Symbolic name meaning all available interfaces
        PORTS = [10001,10002,10003,10004]
        threads = []
        for port in PORTS:   # create threads for each port
            th = threading.Thread(target=server, args=(HOST, port))
            th.start()
            threads.append(th)
            print th,port
     
        print "suite"
    Peut-être qu'il y a une méthode plus.. jolie pour le faire ?

    Je remarque que lorsqu'un thread est relancé, il m'affiche Thread-'chiffre' chiffre correspondant au numéro de thread. Ce numéro s'incrémente sans cesse. Aurais je un problème si cela s'incrémente jusqu'à une éventuelle certaine limite ?

    J'ai aussi lancé une appli telnet qui cause aux 4 ports très régulièrement en auto. Tout semble fonctionner mais parfois, lorsque je coupe cette appli brutalement (je n'arrive pas à me rendre compte si elle était en train d'envoyer quelque chose) j'ai un vilain message d'erreur, exemple:

    Exception in thread Thread-18:
    Traceback (most recent call last):
    File "C:\Python27\lib\threading.py", line 530, in __bootstrap_inner
    self.run()
    File "C:\Python27\lib\threading.py", line 483, in run
    self.__target(*self.__args, **self.__kwargs)
    File "C:\Users\user\Desktop\thread-socket.py", line 35, in server
    handler(clientsock, addr) # loop on 'handler' function
    File "C:\Users\user\Desktop\thread-socket.py", line 13, in handler
    data = clientsock.recv(25) #25 bytes
    error: [Errno 10054] Une connexion existante a dû être fermée par l’hôte distant

    Là je n'ai pas d'autre choix que de rebooter. D'après mes recherches sur le net, c'est un problème de socket. Je crois qu'il reste ouvert (?)
    Merci

    PS: j'ai mis des 'print' partout pour mieux voir et comprendre ce qui se passe, ainsi que des remarques...

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 279
    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 279
    Points : 36 765
    Points
    36 765
    Par défaut
    Salut,

    Un thread démarre un server qui traite les connections client sur un port donné.
    Pourquoi bazarder thread et serveur après avoir servit un client?

    La façon basique pour faire çà sera d'ajouter un "while True":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        ...
        serversock.listen(1)
        while True:
            clientsock, addr = serversock.accept() 
            handler(clientsock, addr) # loop on 'handler' function
    Lorsque la fonction "handler" revient, çà s'occupe du client suivant.

    Tant que votre serveur ne fonctionne pas sans "threads", pas la peine d'en lancer plus d'un.

    Sortez d'une démarche simple et par étapes et patatra!

    - W

    PS: Commencer par "while True:" suppose que vous sachiez arrêter le serveur. Si vous ne savez pas encore, "for _ in range(3):" est un plus petit pas.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 4
    Dernier message: 04/03/2014, 02h42
  2. multi thread et port serie
    Par mich35 dans le forum C#
    Réponses: 4
    Dernier message: 03/07/2012, 08h33
  3. création d'un serveur multi-thread
    Par james23 dans le forum Multithreading
    Réponses: 9
    Dernier message: 30/03/2009, 17h11
  4. question article "Création d'un serveur multi-threads en C++"
    Par contremaitre dans le forum Threads & Processus
    Réponses: 2
    Dernier message: 20/06/2008, 12h01
  5. [BP7] Multi-cpu, multi-core, multi-thread et programme Pascal
    Par Transgarp dans le forum Turbo Pascal
    Réponses: 6
    Dernier message: 07/04/2008, 18h43

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