I have the following code, which is self explanatory:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some data")
# don't close socket just yet...
# do some other stuff with the data (normal string operations)
if s.stillconnected() is true:
s.send("some more data")
if s.stillconnected() is false:
# recreate the socket and reconnect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some more data")
s.close()
How do I implement s.stillconnected()
I do not wish to recreate the socket blindly.
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.
Python takes the automatic shutdown a step further, and says that when a socket is garbage collected, it will automatically do a close if it's needed.
You need to call shutdown() first and then close(), and shutdown takes an argument.
In the server example, .listen() enables a server to accept connections. It makes the server a “listening” socket: # echo-server.py # ... with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() # ... The .listen() method has a backlog parameter.
If the server connection is no longer alive, calling the send method will throw an exception, so you can use a try-exception block to attempt to send data, catch the exception if it's thrown, and reestablish the connection:
try:
s.send("some more data")
except:
# recreate the socket and reconnect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some more data")
EDIT: As per @Jean-Paul Calderone's comments, please consider using the sendall
method, which is a higher level method that sends all the data or throws an error, instead of send
, which is a lower level method that does not guarantee the transmission of all the data, OR use higher level modules like an HTTP library that can handle socket lifecycles.
I've had good results with this variant to check if a socket is closed (negate the result if you want to check if it's still connected):
import logging
import socket
logger = logging.getLogger(__name__)
def is_socket_closed(sock: socket.socket) -> bool:
try:
# this will try to read bytes without blocking and also without removing them from buffer (peek only)
data = sock.recv(16, socket.MSG_DONTWAIT | socket.MSG_PEEK)
if len(data) == 0:
return True
except BlockingIOError:
return False # socket is open and reading from it would block
except ConnectionResetError:
return True # socket was closed for some other reason
except Exception as e:
logger.exception("unexpected exception when checking if a socket is closed")
return False
return False
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