web-dev-qa-db-fra.com

Python: détecter quand un socket se déconnecte pour une raison quelconque?

J'écris une application en Python 2.7.5 en utilisant l'interface de socket brute (import socket).

J'ai besoin de savoir s'il est possible d'enregistrer une sorte d'événement ou de tester facilement à intervalles réguliers, si une connexion socket TCP socket est toujours connectée et établie.

La plupart des conseils que j'ai trouvés disent des choses comme "essayez simplement de lire; s'il est fermé, vous obtiendrez une erreur ou aucun octet". Cependant, parfois je ne suis pas prêt à read mais je veux quand même savoir si le socket est fermé, donc par exemple je peux me reconnecter manuellement immédiatement.

De plus, reading de la socket supprimerait les octets lus dans le tampon, donc reading simplement pour tester la "vivacité" de la connexion ne semble pas faisable.

Avoir un fil d'arrière-plan pour vérifier la vivacité de la connexion serait OK avec moi. Ce thread pourrait vérifier dis une fois par seconde pour voir si la connexion est active; s'il est abandonné, il pourrait appeler une fonction, ou définir une variable ou autre chose pour que l'application sache que la connexion est fermée. Savoir POURQUOI il s'est fermé (réinitialisation par un pair, timeout, etc.) serait encore plus utile ....

Un conseil à ce sujet?

20
fdmillion

Utilisez select comme ce tutoriel le suggère http://docs.python.org/2/howto/sockets.html#non-blocking-sockets

Si un socket se trouve dans la liste lisible en sortie, vous pouvez être aussi proche de certain que nous en avons dans ce métier qu'un recv sur ce socket retournera quelque chose. Même idée pour la liste accessible en écriture. Vous pourrez envoyer quelque chose. Peut-être pas tout ce que vous voulez, mais quelque chose vaut mieux que rien. (En fait, tout socket raisonnablement sain retournera en écriture - cela signifie simplement que l'espace de tampon réseau sortant est disponible.)

... si quelque part dans ces listes d'entrée de sockets en est une qui est morte d'une mort désagréable, la sélection échouera.

C'est le flux que j'utilise habituellement

import select
import socket

ip = '127.0.0.1'
port = 80

conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((ip, port))

while True:
    try:
        ready_to_read, ready_to_write, in_error = \
            select.select([conn,], [conn,], [], 5)
    except select.error:
        conn.shutdown(2)    # 0 = done receiving, 1 = done sending, 2 = both
        conn.close()
        # connection error event here, maybe reconnect
        print 'connection error'
        break
    if len(ready_to_read) > 0:
        recv = conn.recv(2048)
        # do stuff with received data
        print 'received:', recv
    if len(ready_to_write) > 0:
        # connection established, send some stuff
        conn.send('some stuff')
19
Steve Zhan