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 :

Socket qui ne marche qu'un temps limité


Sujet :

Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    passionné
    Inscrit en
    Novembre 2023
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : passionné

    Informations forums :
    Inscription : Novembre 2023
    Messages : 6
    Points : 9
    Points
    9
    Par défaut Socket qui ne marche qu'un temps limité
    Bonjour
    J'ai un circuit Micropython qui se reveille toute les minutes, se connecte au Wifi, ouvre une socket et tente de pousser une chaine de charactere.
    De l'autre coté sur un raspberry j'ai un script python qui ouvre la même socket et essai de la lire.

    Cela marche un certain temps (entre quelques cylcles et quelques heures) mais inevitablement au bout d'un momment le programme coté Raspberry n'arrive plus a lire.
    Si je le redemarre coté Raspberry cela repart...

    J'ai essayé de faire tourner le programme raspberry dans :
    - une boucle "while True" en attente de la socket
    - dans un script lancé par la crontab régulierement

    => meme probleme

    C'est comme si la socket etait saturé au bout d'un certain temps?
    (quand cela ne "marche plus" un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    netstat -tupln |grep 112zz
    tcp        3      0 192.168.xx.yy:112zz    0.0.0.0:*               LISTEN      -
    semble montrer que le process ecoute bien toujours sur le port.

    Le code que je fait tourner coté Raspberry est le suivant :
    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
    #!/usr/bin/env python3
     
    import socket
     
    mySocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, fileno=None)
    mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    hostname = '192.168.xx.yy'
    portno = 11222
    mySocket.bind((hostname, portno))
     
    mySocket.listen(2)
     
     
    if __name__ == "__main__":
        #while True:
        client, client_addr = mySocket.accept()
        print('Connection established with client at address {}'.format(client_addr))
        message = client.recv(1024).decode()
        print(message)
     
        client.close()
    Une idee de comment debugger ou ameliorer mon code pour que la "connection" ne se bloque pas....

    Merci

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

    Le code que vous avez posté est celui d'un serveur (listen) qui attend un client, lit le message, l'affiche et termine... ce qui n'est pas cohérent avec la notion de serveur (qui écoute en permanence).

    Et cela ne reflète pas du tout ce que vous racontez.

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

  3. #3
    Futur Membre du Club
    Homme Profil pro
    passionné
    Inscrit en
    Novembre 2023
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : passionné

    Informations forums :
    Inscription : Novembre 2023
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    Oui je confirme que j'ai posté le code du Raspberry et donc coté Serveur.
    C'est que j'ai du mal m'exprimer ...

    Le code initial avait un "while True: " que j'ai temporairement retirer pour essayer de debugger.
    Mon Client a l'avantage de se connecter a periode constante.

    le code initiale etait

    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
    #!/usr/bin/env python3
     
    import socket
     
    mySocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, fileno=None)
    mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    hostname = '192.168.xx.yy'
    portno = 11222
    mySocket.bind((hostname, portno))
     
    mySocket.listen(2)
     
     
    if __name__ == "__main__":
        while True:
          client, client_addr = mySocket.accept()
          print('Connection established with client at address {}'.format(client_addr))
          message = client.recv(1024).decode()
          print(message)
     
        client.close()
    mais au bout d'un momment bien que le script continue a écouter sur le port, et que le client envoie bien sa demande de connection le serveur ne la recupere pas...

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    A par l'indentation du client.close(), ce code devrait fonctionner.
    On ne peut pas exclure un problème coté OS ou de ressources (c'est lui qui hère les sockets).
    Mais on est plus dans une logique raspberry / réseau que python.

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

  5. #5
    Futur Membre du Club
    Homme Profil pro
    passionné
    Inscrit en
    Novembre 2023
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : passionné

    Informations forums :
    Inscription : Novembre 2023
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    Oups en effet j'ai oublié de l'indenter aussi...

    Je me demandais meme si c'est au niveau de l'OS, si il n'y avait pas moyen de robustifier un peu?
    Par exemple si il accept la connection a "client, client_addr = mySocket.accept()" mais que quelques seconde apres il n'est pas capable de faire le "message = client.recv(1024).decode()" => il ferme la connection et attend la prochaine.
    Cela ne me "gene" pas qu'il puisse de temps en temps ratter des émissions.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par ewok002 Voir le message
    Par exemple si il accept la connection a "client, client_addr = mySocket.accept()" mais que quelques seconde apres il n'est pas capable de faire le "message = client.recv(1024).decode()"
    Vous pouvez essayer d'ajouter des timeouts aux sockets mais exploiter les journaux système pour avoir une idée de ce qu'il se passe ou utiliser un débogueur système pour voir ce qu'il se passe serait préférable.

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

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par ewok002 Voir le message
    Je me demandais meme si c'est au niveau de l'OS, si il n'y avait pas moyen de robustifier un peu?
    Cela ne me "gene" pas qu'il puisse de temps en temps ratter des émissions.
    Déjà puisque la liaison n'est pas en mode connecté, pourquoi la mettre en SOCK_STREAM ? Tu as le mode SOCK_DGRAM justement fait pour ce genre de cas (c'est à dire un client qui écrit "de temps en temps" à un serveur qui s'allume "de temps en temps"). A chaque émission, le client précise à qui elle doit aller et c'est à ce moment là que se fait la connection.

    Un exemple...

    Le serveur
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    import socket
    import sys
    import os
     
    class cSocket:
    	def __init__(self, port):
    		self.__port=port
    		self.__connect=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    		self.__connect.bind(("", port))
    		print("socket {} prête à écouter sur le port {}".format(self.__connect, self.__port))
    	# __init__()
     
    	def __del__(self):
    		self.__connect.close()
    		print("socket {} sur port {} terminée".format(self.__connect, self.__port))
    	# __del__()
     
    	# Ecoute
    	def listen(self):
    		while True:
    			try:
    				(data, infos)=self.__connect.recvfrom(1024)
    			except KeyboardInterrupt:
    				break
    			# try
    			try: host=socket.gethostbyaddr(infos[0])[0]
    			except socket.herror as e: host="?"
    			txt=data.decode("utf-8")
    			print("adr=[{}]: [{}]{}".format(host,	txt, " => Arrêt du client" if txt == "EOT" else ""))
    		# while
    		print("socket {} sur port {} terminé !!!".format(self.__connect, self.__port))
    	# listen()
    # class cSocket
     
    if __name__ == "__main__":
    	cSocket(int(sys.argv[1])).listen()
    Tu remarqueras accessoirement que pour le bind(), le serveur n'a pas besoin de mettre une adresse puisque c'est lui-même. Ca t'évite ce hostname = '192.168.xx.yy' inutile de ton code.
    Et ce serveur tu le lances en lui donnant le numéro de port en paramètre.

    Et le client
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    import socket
    import sys
     
    class cSocket:
    	def __init__(self, port, host="localhost"):
    		self.__host=host
    		self.__port=port
    		self.__dialog=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    		print("socket {} prête pour {} sur le port {}".format(self.__dialog, host, port))
    	# __init__()
     
    	def dialogue(self):
    		while True:
    			msg=input("Tapez votre message (EOT pour quitter): ")
    			self.__dialog.sendto(msg.encode("utf-8"), (self.__host, self.__port))
    			if msg == "EOT":
    				print("Client teminé")
    				break
    			# if
    		# while
    	# dialogue()
    # class cSocket
     
    if __name__ == "__main__":
    	cSocket(int(sys.argv[1]), sys.argv[2] if len(sys.argv) > 2 else "localhost").dialogue()
    Lui tu le lances en lui donnant le numéro de port et éventuellement l'adresse du serveur (si le serveur tourne sur un autre host).

    Ensuite dans le client tu tapes ce que tu veux et tout ce que tu tapes est affiché par le serveur (sans perdre quoi que ce soit). Et tu termines avec la string "EOT".
    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]

  8. #8
    Futur Membre du Club
    Homme Profil pro
    passionné
    Inscrit en
    Novembre 2023
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : passionné

    Informations forums :
    Inscription : Novembre 2023
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    MErci pour toutes ces infos :
    en // j'ai vu des site qui recommandent de passer en multithreading pour que quand une connection plante les suivantes marchent.

    Je suis en train de tester en endurance un bout de code comme ca :

    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
    #!/usr/bin/env python3
     
    import socket, time
    from miscSchugartHome import writeLog
     
    from _thread import *
     
    host         = '192.168.xx.yy'
    socketPort   = 112zz
     
     
    def client_handler(connection):
        message = connection.recv(1024).decode()
        writeLog('Message : %s'%message, 'INFO', 'NoMail')    
     
        connection.close()
     
    def accept_connections(ServerSocket):
        Client, address = ServerSocket.accept()
        writeLog('Connected to: ' + address[0] + ':' + str(address[1]), 'INFO', 'NoMail')
        if address[0] in ['192.168.xx.yy']:
            start_new_thread(client_handler, (Client, ))
     
    def start_server(host, socketPort):
        serverSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, fileno=None)
        serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        try:
            serverSocket.bind((host, socketPort))
        except socket.error as e:
            print(str(e))
        writeLog('Socket bound to address {} and port number {}'.format(host, socketPort), 'INFO', 'NoMail')
        serverSocket.listen()
     
        while True:
            accept_connections(serverSocket)
     
     
    if __name__ == "__main__":
        # Start Socket server
        start_server(host, socketPort, shareMem)
    Si ca marche pas mieux je tenterai d'implementer ton client serveur avec "SOCK_DGRAM"

    Merci

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Déjà puisque la liaison n'est pas en mode connecté, pourquoi la mettre en SOCK_STREAM ? Tu as le mode SOCK_DGRAM
    HTTP n'est pas plus en mode "connecté" (par défaut) et ce sera du STREAM.
    Les datagram c'est lorsqu'on n'a pas besoin de savoir si le message arrive ou pas (ce qui est une restriction forte).
    En tous cas, changer de problème n'apporte pas grand chose quand à a question posée (pourquoi le serveur se bloque au bout d'un certain temps).

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

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ewok002 Voir le message
    en // j'ai vu des site qui recommandent de passer en multithreading pour que quand une connection plante les suivantes marchent.
    En mode STREAM oui car une fois le client connecté il le reste donc il faut un process (fils) dédié au dialogue pendant que le père se tient prêt à prendre un autre client.

    Un exemple analogue en mode STREAM
    Le serveur
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    import socket
    import sys
    import os
     
    class cSocket:
    	def __init__(self, port):
    		self.__port=port
    		self.__connect=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    		self.__connect.bind(("", self.__port))
    		print("socket {} prêt à écouter sur le port {}".format(self.__connect, self.__port))
    	# __init__()
     
    	def __del__(self):
    		self.__connect.close()
    		print("socket {} sur port {} terminé".format(self.__connect, self.__port))
    	# __del__()
     
    	# Ecoute
    	def listen(self):
    		self.__connect.listen(1)
    		while True:
    			try: (dialog, infos)=self.__connect.accept()
    			except KeyboardInterrupt: break
    			pid=os.fork()
    			if pid == 0:
    				self.__client(dialog, infos)
    				exit(0)
    			# if
    		# while
    	# listen()
     
    	# Gestion du client connecté
    	def __client(self, dialog, infos):
    		# Récupération hostname client
    		try: host=socket.gethostbyaddr(infos[0])[0]
    		except socket.herror as e: host="?"
    		print("client pid={} - Entrée émise [adr={}]".format(os.getpid(), host))
     
    		# Lecture client
    		while True:
    			data=dialog.recv(1024).decode("utf-8")
    			print("client pid={}: Message: [{}]{}".format(os.getpid(), data, " => Arrêt du client" if data == "EOT" else ""))
    			if data == "EOT": break
    		# while
    		print("client pid={} - Entrée raccrochée [adr={}]".format(os.getpid(), host))
    	# __client()
    # class cSocket
     
    if __name__ == "__main__":
    	cSocket(int(sys.argv[1])).listen()

    Le client
    Code python : 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
    #!/usr/bin/env python3
    # coding: utf-8
     
    import socket
    import sys
     
    class cSocket:
    	def __init__(self, port, host="localhost"):
    		self.__port=port
    		self.__host=host
    		self.__dialog=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    		self.__dialog.connect((host, port))
    		print("socket {} connecté avec {} sur le port {}".format(self.__dialog, self.__host, self.__port))
    	# __init__()
     
    	def __del__(self):
    		self.__dialog.close()
    		print("socket {} avec {} sur port {} terminé".format(self.__dialog, self.__host, self.__port))
     
    	def dialogue(self):
    		while True:
    			msg=input("Tapez votre message (EOT pour quitter): ")
    			self.__dialog.send(msg.encode("utf-8"))
    			if msg == "EOT":
    				print("Client teminé")
    				break
    			# if
    		# while
    	# dialogue()
    # class cSocket
     
    if __name__ == "__main__":
    	cSocket(int(sys.argv[1]), sys.argv[2] if len(sys.argv) > 2 else "localhost").dialogue()
    Dans cet exemple, à chaque client qui se connecte, le serveur lui dédie un process pour l'écouter (ok ici c'est du fork() car j'ai écrit cet exemple sous Linux mais la technologie thread reste aussi possible).

    Mais pas besoin avec du DGRAM car en mode DGRAM, chaque information envoyée génère sa propre connection indépendante qui est récupérée par le serveur de façon isolée. Le seul souci éventuel c'est que si n informations sont envoyées de façon séquentielle très rapide, il est possible que l'information "n+1" arrive avant l'information "n".
    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]

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    En mode STREAM oui car une fois le client connecté il le reste donc il faut un process (fils) dédié au dialogue pendant que le père se tient prêt à prendre un autre client.
    Sauf qu'ici, il n'y qu'un client qui envoie un message de temps en temps qu'on se contente de lire pour fermer la connexion et attendre le message suivant.

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

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Sauf qu'ici, il n'y qu'un client qui envoie un message de temps en temps qu'on se contente de lire pour fermer la connexion et attendre le message suivant.
    D'où ma première réponse qui plébiscite le mode DGRAM fait justement pour ce genre de cas, réponse que je renforce par ma dernière remarque "Mais pas besoin avec du DGRAM car en mode DGRAM..."
    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]

  13. #13
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    D'où ma première réponse qui plébiscite le mode DGRAM fait justement pour ce genre de cas,
    Quel est le rapport entre STREAM et DGRAM avec le nombre de clients à gérer? Sortez l'URL d'un article sérieux corroborant cela et on en reparle.
    De plus dans un forum technique, "on ne plebiscite pas", on travaille avec du factuel et ici je ne vois pas en quoi changer de protocole explique le problème rencontré (autant changer d'OS et en prendre un sur lequel ce soucis n'apparait pas).

    Citation Envoyé par ewok002 Voir le message
    en // j'ai vu des site qui recommandent de passer en multithreading pour que quand une connection plante les suivantes marchent
    Ce que vous décrivez n'est pas une connexion qui plante mais une connexion qui se bloque. Dans la pratique, ça bloquera aussi des ressources (mémoire, descripteurs de fichiers,...) qui ne sont pas infinies. Si elles ne sont pas rendues assez vite, c'est l'ensemble du système qui risque d'avoir des problèmes.

    Exemple de problème similaire rencontré ou le coupable semble être la configuration du routeur WIFI => contourner le problème, aurait été ici de laisser un équipement défaillant foutre la grouille ailleurs.

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

  14. #14
    Futur Membre du Club
    Homme Profil pro
    passionné
    Inscrit en
    Novembre 2023
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : passionné

    Informations forums :
    Inscription : Novembre 2023
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    Complètement d'accord avec toi.
    Ce que je fais ne resoud pas le problème...
    Mais n'ayant pas trop d'idde ni peut etre les connaissances necessaire aux debug j'ai imaginé que :
    Certaines connexions se passent mal et comme les unes sont a la suite des autres cela bloque l'ensemble.
    Si la connexion qui freeze est dans un thread, comme il y a des timeout TCP a 2h apparemment j'en aurait en effet potentiellement une dizaine en // alors qu'une seul devrai suffir.
    Mais je pense que le raspberry peut se le permettre.

    Malgré tout je continue a surveiller la charge
    Avec le multi thread "pour l'instant" cela marche toujours (je n'ai jamais durée aussi longtemps, 4heures...).
    et le process python n'apparait pas dans top... pas assez de conso ;-)

    PS : cela peut en effet etre un pb au niveau du routeur, (Wifi je suis plus sceptique) je vais regarder cette piste

  15. #15
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Quel est le rapport entre STREAM et DGRAM avec le nombre de clients à gérer?
    Tu déformes volontairement mes propos en isolant une partie de ceux-ci (et, comme par hasard, la partie la moins pertinente). Tu sais PARFAITEMENT que ce n'est pas en fonction du "nombre de clients" mais en fonction de la façon dont les clients envoient des informations (je l'ai écrit dans mon premier post). En mode STREAM il y a établissement d'une liaison unique avec le client puis les informations du client passent par cette liaison (un peu l'équivalent d'un appel téléphonique). Cela nécessite donc que la liaison reste ouverte tant qu'il y a des informations. Et cela nécessite aussi que le serveur dédie chaque communication à un process particulier, lui permettant ainsi de rester libre pour recevoir d'autres clients. Parce que sans ça, les messages des autres clients n'arrivent pas (et c'est facile à tester, suffit de commenter la ligne pid=fork() et exit(0) de mon exemple précédent).
    En mode DGRAM chaque information envoyée crée sa propre connexion avec le serveur qui reste donc libre de toutes contraintes (un truc lui arrive il le traite et passe au suivant, un peu comme des lettres qu'on reçoit par la poste).
    Ensuite (argumentaire moins fort mais non nul), il se trouve que si un serveur léger fonctionne pour n clients, il fonctionnera alors d'autant mieux s'il n'y a qu'un seul client (ce qui semble être le cas ici).

    Citation Envoyé par wiztricks Voir le message
    Sortez l'URL d'un article sérieux corroborant cela et on en reparle.
    Ah oui? Je pensais qu'on était ici pour donner des avis, avis étayés par 1) l'expérience et 2) les arguments. S'il faut maintenant des URL pour prouver nos écrits, là ça va devenir compliqué pour tout le monde de venir poster leurs réponses sur les problèmes rencontrés.
    Mais j'en ai quand-même trouvé un => https://tech-lib.fr/datagram/ qui dit (je cite) "Le principal avantage des datagrammes est qu'ils fournissent un moyen de communication sur un réseau à commutation de paquets sans que l'expéditeur et le destinataire aient besoin d'être connectés à tout moment. Cela les rend idéaux pour les applications qui doivent envoyer des données sur un réseau sans avoir besoin d'une connexion permanente". Voilà, idéal pour des envois sans nécessité de connexion permanente, comme c'est le cas ici. Mais bien évidemment comme "môssieur" ne réclame pas seulement des URL mais en plus des URL d'articles "sérieux", il aura tout le loisir de dénigrer comme il l'entend la "sériosité" de cette URL...
    Ceci dit ce n'est pas à toi que je parle mais au PO donc je n'ai rien à te prouver. Mais contrairement à toi, je donne des possibilités appuyées par des codes d'exemples. Toi tu es juste là à te dandiner avec tes "ce code devrait fonctionner", "vous pouvez essayer ceci ou cela" et "justifiez vos affirmations (tandis que moi W je m'autorise à n'en justifier aucune) par des URL d'articles"


    Citation Envoyé par wiztricks Voir le message
    De plus dans un forum technique, "on ne plebiscite pas", on travaille avec du factuel et ici je ne vois pas en quoi changer de protocole explique le problème rencontré
    Tu as raison, le verbe est mal adapté. J'aurais plutôt dû dire que je donnais une autre piste possible que je trouve plus adaptée à la façon dont le client envoie ses infos. En mode STREAM il faut que la liaison reste ouverte. Si quelque part elle est fermée, les informations suivantes n'arrivent plus. Ce qui, ô surprise, correspond assez bien avec le problème tel qu'il a été décrit. De plus en mode STREAM il faut que le serveur dédie un process au dialogue, ce qui n'est pas le cas dans le code montré par le PO.
    En mode DGRAM pas besoin de liaison ouverte, et pas besoin de process dédié. Alors autant éviter le compliqué et faire simple en ne changeant qu'un seul paramètre (ce qui pourrait bien, en plus, résoudre le souci). Et ce d'autant plus que le client décrit fonctionne selon le schéma DGRAM (il se connecte, envoie une et une seule info et quitte). Alors quoi? Si tu dois aller naviguer, vas-tu mettre des boudins gonflables à ta voiture ou plutôt prendre un bateau?

    Citation Envoyé par ewok002 Voir le message
    PS : cela peut en effet etre un pb au niveau du routeur, (Wifi je suis plus sceptique) je vais regarder cette piste
    La première piste à regarder est de tester ton code en local sur ta machine de test. Ca éliminera les soucis de connectique. C'est d'ailleurs généralement la base du développement des protocoles réseaux. On commence par les développer en local, en utilisant "localhost" qui justement est fait pour ça. Là on met au point son code qu'on peut tester sans craindre les soucis liés à la connectique.
    Ensuite (ce n'est pas obligatoire mais ça reste intéressant), on reteste en local mais en passant cette fois par sa propre adresse ip. Là les communications passent par la carte réseau. On peut alors checker des trucs comme le firewall et autres emmerdements.
    Et enfin une fois le code validé là tu peux aller le mettre sur ton rasberry et là si ça échoue tu auras au-moins une direction de recherche plus précise (qui ne sera pas ton code).
    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]

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ah oui? Je pensais qu'on était ici pour donner des avis, avis étayés par 1) l'expérience et 2) les arguments.
    J'ai donné mon avis: il est improbable que ce soit un problème python et il faut regarder côté OS ou réseau (et demander de l'aide dans les forums adhoc).... Et je ne vais pas faire des théories à 2 balles ici juste parce que ce n'est pas le lieu (ou des experts pourraient me contredire).

    Masquer le problème pour faire autre chose (et ignorer les pertes de messages) n'est pas une solution ni même un contournement puisque pour l'instant nous ignorons la cause du problème.

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

  17. #17
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    J'ai donné mon avis: il est improbable que ce soit un problème python
    Je n'ai pas dit non plus que c'en était un. Mais puisqu'on est en Python, autant poster des codes Python. On aurait été en C j'aurais posté les mêmes en C

    Citation Envoyé par wiztricks Voir le message
    et il faut regarder côté OS ou réseau
    Justement mes exemples (qui fonctionnent en local) peuvent aider à faire ces vérifications

    Citation Envoyé par wiztricks Voir le message
    Et je ne vais pas faire des théories à 2 balles ici juste parce que ce n'est pas le lieu (ou des experts pourraient me contredire).
    Tu es libre sur ce point mais tu n'as rien à dire contre ceux qui en font. C'est en faisant des théories qu'on progresse.

    Citation Envoyé par wiztricks Voir le message
    Masquer le problème pour faire autre chose (et ignorer les pertes de messages) n'est pas une solution ni même un contournement puisque pour l'instant nous ignorons la cause du problème.
    Ce n'est pas le masquer que d'essayer un code fonctionnel, c'est éliminer des causes possibles. Quant aux "pertes des messages" pour l'instant il n'y a que toi que ça gêne, on verra l'avis du PO sur ce point (et de toute façon des pertes "possibles" ce ne sera jamais pire que les pertes "réelles" de l'état actuel). Accessoirement tu remarqueras que j'ai aussi posté un code basé sur le mode STREAM...
    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]

  18. #18
    Futur Membre du Club
    Homme Profil pro
    passionné
    Inscrit en
    Novembre 2023
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : passionné

    Informations forums :
    Inscription : Novembre 2023
    Messages : 6
    Points : 9
    Points
    9
    Par défaut
    Euh faut pas s'enerver :-)

    Je ne suis pas un développeur ... juste un amateur qui fait de la domotique depuis plusieurs année qui apprend Python sur le tas.
    Donc si on me propose une solution qui marche mais qui ne resoud pas forcement le problème c'est deja bien!

    Ensuite a force je fini en général par trouver les problèmes mais cela prend du temps :-)

    Merci merci pour votre aide et zen ;-)

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par ewok002 Voir le message
    Je ne suis pas un développeur ... juste un amateur qui fait de la domotique depuis plusieurs année qui apprend Python sur le tas.
    Justement, vous n'êtes peut être pas en capacité de juger de la pertinence d'utiliser UDP ou de rester sur TCP.

    Ces constructions ont été faites par l'homme avec des raisons et motivations bien précises: on sait (à priori) quand on doit ou pas utiliser tel outil parce que...

    Le protocole HTTP V1.0 ressemble à ce que vous faites: envoi d'un simple message, attente de la réponse du serveur et fermeture de la connexion. (votre client n'attend pas la réponse du serveur).

    C'est vrai que TCP est lourd dans ce cas, mais pour avoir la même fiabilité au dessus d'UDP, il faut le paquet de lignes de code qui s'appelle QUIC "au dessus".... ce qui n'est pas si anodin (et il y a des tas de vidéos sur youtube pour avoir les détails).

    Pour revenir à votre problème, la seule bonne raison pour que le serveur se bloque attendant la réception d'un message est que le message en question n'ait pas été émis ou ne soit pas transmis

    Comme il n'y a pas de timeout, ça bloque tant que.... et l'ajout de ce timeout se fait facilement:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if __name__ == "__main__":
        while True:
          client, client_addr = mySocket.accept()
          print('Connection established with client at address {}'.format(client_addr))
          client.settimeout(1)
          try:
                 message = client.recv(1024)
          except:
                 pass
          else:
                 print(message.decode())
          client.close()
    Comme le client émet un message par minute, 1 seconde de timeout suffit (et évite de se trimbaler un paquet de threads +/- zombies).

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

Discussions similaires

  1. [XL-2019] Cellule qui clignote pendant un temps limité
    Par EAU24 dans le forum Macros et VBA Excel
    Réponses: 15
    Dernier message: 23/09/2019, 17h00
  2. Réponses: 2
    Dernier message: 01/12/2009, 07h58
  3. Socket, recv et select qui ne marche pas
    Par Zapan dans le forum Réseau
    Réponses: 18
    Dernier message: 30/06/2006, 20h19
  4. Socket qui ne marche pas
    Par Guillaume602 dans le forum C++
    Réponses: 4
    Dernier message: 15/01/2006, 14h07
  5. Réponses: 9
    Dernier message: 07/05/2003, 12h57

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