web-dev-qa-db-fra.com

Comment utiliser correctement python socket.settimeout ()

Autant que je sache, lorsque vous appelez socket.settimeout(value) et que vous définissez une valeur flottante supérieure à 0,0, cette socket déclenche un scocket.timeout lorsqu'un appel à, par exemple, socket.recv Doit attendez plus longtemps que la valeur spécifiée.

Mais imaginez que je dois recevoir une grande quantité de données, et que je dois appeler recv() plusieurs fois, alors comment la temporisation affecte-t-elle cela?

Étant donné le code suivant:

to_receive = # an integer representing the bytes we want to receive
socket = # a connected socket

socket.settimeout(20)
received = 0
received_data = b""

while received < to_receive:
    tmp = socket.recv(4096)
    if len(tmp) == 0:
        raise Exception()
    received += len(tmp)
    received_data += tmp

socket.settimeout(None)

La troisième ligne du code définit le délai d'expiration du socket à 20 secondes. Ce délai d'attente réinitialise-t-il chaque itération? Le délai d'attente ne sera-t-il augmenté que si l'une de ces itérations dure plus de 20 secondes?

A) Comment puis-je le recoder afin qu'il déclenche une exception s'il faut plus de 20 secondes pour recevoir toutes les données attendues?

B) Si je ne règle pas le délai d'attente sur Aucun après avoir lu toutes les données, quelque chose de mal pourrait-il arriver? (la connexion est permanente et davantage de données pourraient être demandées à l'avenir).

10
Jorky10

Le délai d'attente s'applique à un seul appel à une opération de lecture/écriture de socket. Donc, le prochain appel sera encore 20 secondes.

A) Pour avoir un délai partagé par plusieurs appels consécutifs, vous devrez le suivre manuellement. Quelque chose dans ce sens:

deadline = time.time() + 20.0
while not data_received:
    if time.time() >= deadline:
        raise Exception() # ...
    socket.settimeout(deadline - time.time())
    socket.read() # ...

B) Tout code qui utilise un socket avec un délai d'expiration et n'est pas prêt à gérer socket.timeout l'exception échouera probablement. Il est plus fiable de se souvenir de la valeur du délai d'attente du socket avant de commencer votre opération et de la restaurer lorsque vous avez terminé:

def my_socket_function(socket, ...):
    # some initialization and stuff
    old_timeout = socket.gettimeout() # Save
    # do your stuff with socket
    socket.settimeout(old_timeout) # Restore
    # etc

De cette façon, votre fonction n'affectera pas le fonctionnement du code qui l'appelle, peu importe ce que l'un ou l'autre fait avec le délai d'expiration du socket.

4
Lav

Le délai d'attente s'applique à chaque appel à recv ().

A) Utilisez simplement votre délai d'expiration existant et appelez recv (to_receive) - c'est-à-dire Essayez de recevoir toutes les données en un seul appel recv - en fait, je ne vois pas pourquoi vous ne devriez pas l'utiliser comme mode par défaut

B) Rien de mauvais ne pourrait arriver, mais tout autre code utilisant ce socket doit être conscient de la gestion du délai d'attente.

Sur votre code existant, l'appel recv () ne devrait-il pas être recv (max (4096, to_receive-received)) - de cette façon, vous ne consommerez pas involontairement les données qui suivent après les octets to_receive.

1
barny

Voir mon script serveur, vous aurez l'idée de l'utiliser correctement.

import socket
import sys
fragments = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("192.168.1.4",9001))
s.listen(5)
while True:
    c,a = s.accept()
    c.settimeout(10.0)
    print "Someone came in Server from %s and port %s" %(a[0],a[1])
    c.send("Welcome to system")
    while True:
        chunk = c.recv(2048)
        if not chunk.strip():
            break
        else:
            fragments.append(chunk)
            continue
    combiner = "".join(fragments)
    print combiner
    shutdown = str(raw_input("Wanna Quit(Y/y) or (N/n): "))
    if shutdown == 'Y' or shutdown == 'y':
        c.close()
        sys.exit()
    else:
        continue

Ce script est juste pour vous donner une idée de la socket.settimeout ().

0
Himanshu Kanojiya