简体   繁体   中英

Python: detect when a socket disconnects for any reason?

I'm writing an app in Python 2.7.5 using the raw socket interface ( import socket ).

I need to know if there's a way I can either register some sort of event, or easily test at a regular interval, if a TCP socket connection is still connected and established.

Most of the advice I've found says things like "just try to read from it; if it's closed you'll get an error or no bytes." However, sometimes I'm not ready to read from it but I still want to know if the socket gets closed, so for example I can manually reconnect immediately.

Also, read ing from the socket would remove the bytes read from the buffer, so read ing simply to test for connection "liveness" doesn't seem feasible.

Having a background thread to check for connection liveness would be OK with me. That thread could check say once per second to see if the connection is live; if it is dropped, then it could call a function, or set a variable or some other thing so that the app knows the connection closed. Knowing WHY it closed (reset by peer, timeout, etc) would be even more useful....

Any advice on this?

Use select like this tutorial suggested http://docs.python.org/3/howto/sockets.html#non-blocking-sockets

If a socket is in the output readable list, you can be as-close-to-certain-as-we-ever-get-in-this-business that a recv on that socket will return something. Same idea for the writable list. You'll be able to send something. Maybe not all you want to, but something is better than nothing. (Actually, any reasonably healthy socket will return as writable - it just means outbound network buffer space is available.)

... if somewhere in those input lists of sockets is one which has died a nasty death, the select will fail.

(The last paragraph is no longer there in the Python 3 version.)

This is the flow I usually use

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(f'received: {recv}')
    if len(ready_to_write) > 0:
        # connection established, send some stuff
        conn.send('some stuff')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM