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'.
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.
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.
It means that your given host name ' ' is invalid (gai stands for getaddrinfo() ).
bind() − This method binds the address (hostname, port number) to the socket.
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 MySocket
s, 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.
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