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?
If you need to determine the current state of the connection, make a nonblocking, zero-byte Send call. If the call returns successfully or throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected.
The most obvious way to accomplish this is having that process call read on the socket for a connection and check whether read returns 0 (i.e. reads zero bytes from the socket), in which case we know that the connection has been closed.
To close the connection, break the while loop. Garbage collection will remove the thread or process but join will ensure none get left behind. Persistent sockets close when the user closes them or they timeout.
It is only ever necessary to shutdown a socket for writing if (1) you have forked the process and definitely want to send the FIN now, or (2) you are engaging in a mutual read-to-EOS protocol such that both peers close at the same time. Otherwise close() is sufficient. The Python documentation should be corrected.
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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With