Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending socket.socket with a new attribute

I wish to extend Python socket.socket with a new attribute (in particular, a queue.Queue, but could be anything else). I am trying to decide whether I should use inheritance or composition, but at some point both pose a problem I am not sure how to solve:

A) If I use inheritance, with something like:

class MySocket(socket.socket):
    def __init__(self, *args, **kwargs):
        socket.socket.__init__(self, *args, **kwargs)
        self.queue = queue.Queue()

then I have problems when I use operations like

connection, client_address = s.accept()

because the accept method of sockets returns objects of type socket.socket, and not of type MySocket, and I am not sure how to convert one into the other. If there is is a trivial OOP way to do this, I do not know it.

B) The problem before is trivially solved if I used composition instead:

class MySocket(socket.socket):
    def __init__(self, true_socket):
        self.true_socket = true_socket
        self.queue = queue.Queue()

I would simply implement something like

def accept(self, *args, **kwargs):
    con, cli = socket.socket.accept(self, *args, **kwargs)
    return self.__class__(con), cli

But then I have another problem. When I need to do

readable, writable, exceptional = select.select(inputs, outputs, inputs)

select works for socket.socket. With the A) version I would expect this to work just as is, but with composition, now that MySockets are not instances of socket.socket, select is broken.

So, what is the best, pythonistic approach for this?

EDIT: I forgot to say that the first thing I tried was to add the attribute directly to instances of `socket.socket':

s = socket.socket(...)
s.queue = queue.Queue()

but I got an exception saying the attribute is unknown for 'socket.socket'.

like image 784
zeycus Avatar asked Jul 20 '17 06:07

zeycus


People also ask

What is Sock_stream?

SOCK_STREAM. Provides sequenced, two-way byte streams with a transmission mechanism for stream data. This socket type transmits data on a reliable basis, in order, and with out-of-band capabilities. In the UNIX domain, the SOCK_STREAM socket type works like a pipe.

What is socket Af_inet in Python?

AF_INET is the Internet address family for IPv4. SOCK_STREAM is the socket type for TCP, the protocol that will be used to transport messages in the network. The . bind() method is used to associate the socket with a specific network interface and port number: # echo-server.py # ... with socket.

What is Gaierror?

It means that your given host name ' ' is invalid (gai stands for getaddrinfo() ).

Which method of the socket module allows you to associate a host and a port with a specific socket?

bind() − This method binds the address (hostname, port number) to the socket.


1 Answers

You can use the following, based on socket.socket.dup() in Lib/socket.py:

    import _socket

    class MySocket(socket.socket):
        def __init__(self, *args, **kwargs):
            super(MySocket, self).__init__(*args, **kwargs)
            self.queue = queue.Queue

        @classmethod
        def copy(cls, sock):
            fd = _socket.dup(sock.fileno())
            copy = cls(sock.family, sock.type, sock.proto, fileno=fd)
            copy.settimeout(sock.gettimeout())
            return copy

You can now use the constructor to create new MySockets, or use MySocket.copy() to create a MySocket from an existing socket.socket. Note that in most cases you should close the original socket after creating the copy.

like image 195
augurar Avatar answered Oct 11 '22 08:10

augurar