Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - How to check if socket is still connected

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.

like image 873
AK_ Avatar asked Dec 29 '17 15:12

AK_


People also ask

How do you know if a socket is closed?

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.

Does Python automatically close socket?

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.

How do you close a socket on a Python server?

You need to call shutdown() first and then close(), and shutdown takes an argument.

How do I run a socket in Python?

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.


2 Answers

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.

like image 124
Robert Valencia Avatar answered Oct 19 '22 10:10

Robert Valencia


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
like image 13
Michael Petrov Avatar answered Oct 19 '22 09:10

Michael Petrov