2013-06-30 13 views
13

Piszę aplikację w Pythonie 2.7.5, używając interfejsu gniazda raw (import socket).Python: wykrywanie, gdy gniazdo zostanie odłączone z jakiegokolwiek powodu?

Muszę wiedzieć, czy istnieje sposób, w jaki mogę zarejestrować jakieś zdarzenie lub łatwo przetestować w regularnych odstępach czasu, jeśli połączenie z gniazdem TCP jest nadal połączone i ustanowione.

Większość porad, które znalazłem, mówi: "po prostu spróbuj odczytać z niego, jeśli jest zamknięte, dostaniesz błąd lub nie będzie żadnych bajtów". Czasami jednak nie jestem gotowy na to, aby read, ale nadal chcę wiedzieć, czy gniazdo zostanie zamknięte, więc na przykład mogę ręcznie ponownie połączyć się natychmiast.

Ponadto, z gniazda usunięto by bajty odczytane z bufora, więc read po prostu w celu przetestowania połączenia "na żywo" nie wydaje się wykonalne.

Posiadanie wątku tła w celu sprawdzenia żywotności połączenia byłoby w porządku ze mną. Ten wątek może sprawdzać raz na sekundę, aby sprawdzić, czy połączenie jest aktywne; jeśli zostanie upuszczone, może wywołać funkcję lub ustawić zmienną lub inną rzecz, aby aplikacja wiedziała, że ​​połączenie zostało zamknięte. Znajomość DLACZEGO zamknął (reset przez peer, timeout, itp.) Byłoby jeszcze bardziej przydatne ....

Wszelkie porady na ten temat?

+0

na posix; użyj 'select()' (lub 'epoll()' dla Linux) – tMC

+0

Powiązane: http://stackoverflow.com/questions/17705239/is-there-a-way-to-detect-that-tcp-socket-has -been-closed-by-the-remote-peer-wit (TL; DR: nie ma dobrego sposobu, aby dowiedzieć się, czy połączenie zostało zamknięte, chyba że chcesz przeczytać wszystkie bajty przychodzące z gniazda; Gniazda TCP są implementowane w ten sposób celowo, ponieważ opierają się na idei porządkowania zdarzeń FIFO, tzn. Chcą, abyś odczytywał przychodzące dane w kolejności i tylko dowiedział się o końcu strumienia po przeczytaniu go wszystkie) –

Odpowiedz

13

Zastosowanie select jak tym poradniku sugeruje http://docs.python.org/2/howto/sockets.html#non-blocking-sockets

Jeśli gniazdo znajduje się na liście czytelnej wyjściowego, możesz być jak-close-to-pewien-jak-my-nigdy-get-in-this -biznes, że recv na tym gnieździe zwróci coś. Ten sam pomysł na listę zapisywalną. Będziesz mógł wysłać coś. Może nie wszystko, co chcesz, ale coś jest lepsze niż nic. (Właściwie każde rozsądnie zdrowe gniazdo zostanie zwrócone jako zapisywalne - oznacza to tylko, że dostępna jest przestrzeń bufora wychodzącego.)

... jeśli gdzieś w tych wejściowych listach gniazd jest taka, która umarła śmiercią, wybierz zawieść.

to przepływ Zwykle używać

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') 
Powiązane problemy