Cum se utilizează python socket.settimeout() în mod corespunzător (Programare, Python, Prize, Tcp)

Jorky10 a intrebat.

Din câte știu eu, atunci când apelați socket.settimeout(value) și setați o valoare float mai mare decât 0.0, acel socket va ridica un scocket.timeout atunci când un apel la, de exemplu, socket.recv trebuie să aștepte mai mult decât valoarea specificată.

Dar imaginați-vă că trebuie să primesc o cantitate mare de date și trebuie să apelez la recv() de mai multe ori, atunci cum afectează acest lucru settimeout?

Având în vedere următorul cod:

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)

A treia linie a codului setează timeout-ul socket-ului la 20 de secunde. Acest timeout se resetează la fiecare iterație? Va fi ridicat timeout doar dacă una dintre aceste iterații durează mai mult de 20 de secunde?

A) Cum aș putea recodifica astfel încât să se ridice o excepție dacă durează mai mult de 20 de secunde pentru a primi toate datele așteptate?

B) Dacă nu setez timeout-ul la None după ce am citit toate datele, s-ar putea întâmpla ceva rău? (conexiunea este keep-alive și ar putea fi solicitate mai multe date în viitor).

3 răspunsuri
Lav

Timeout se aplică la un singur apel la operațiunea de citire/scriere a socket-ului. Deci, următorul apel va fi din nou de 20 de secunde.

A) Pentru a avea un timeout împărțit de mai multe apeluri consecvente, va trebui să îl urmăriți manual. Ceva de genul acesta:

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

B) Orice cod care folosește un socket cu un timeout și nu este pregătit să gestioneze socket.timeout excepția va eșua probabil. Este mai fiabil să vă amintiți valoarea timeout-ului socket-ului înainte de a începe operațiunea și să o restaurați când ați terminat:

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

În acest fel, funcția dvs. nu va afecta funcționarea codului care o apelează, indiferent de ceea ce face oricare dintre ele cu timeout-ul socket-ului.

barny

Timeout-ul se aplică la fiecare apel la recv().

A) folosiți pur și simplu timeout-ul existent și apelați recv(to_receive) – adică încercați să primiți toate datele într-un singur apel recv – de fapt, nu văd de ce nu ar trebui să folosiți acest lucru ca mod implicit de funcționare

B) Nu, nu s-ar putea întâmpla nimic rău, dar orice alt cod care utilizează acel socket trebuie să fie conștient de gestionarea timeout-ului.

În cazul codului dvs. existent, apelul recv() nu ar trebui să fie recv(max(4096,to_receive-received)) – în acest fel nu veți consuma în mod neintenționat orice date care urmează după octeții to_receive.

Himanshu Kanojiya

Vedeți scriptul meu de server, veți avea ideea de a-l utiliza în mod corespunzător.

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

Acest script este doar pentru a vă da o idee despre socket.settimeout().

Comentarii

  • Se pare că trece la starea de blocare după 10 sec. Dar nu sunt sigur de ce este util. Ce se întâmplă dacă nu folosiți settimeout? –  > Por Dami.