Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Subclassing socket

Reply
Thread Tools

Subclassing socket

 
 
groups.20.thebriguy@spamgourmet.com
Guest
Posts: n/a
 
      12-21-2005
socket objects have a little quirk. If you try to receive 0 bytes on a
blocking socket, they block. That is, if I call recv(0), it blocks
(until some data arrives).

I think that's wrong, but I don't want to argue that. I would like to
create a subclass of socket that fixes the problem. Ideally, something
like:

class new_socket(socket):
def recv( self, bufsize, flags=0 ):
if bufsize == 0:
return ""
else:
return socket.recv( bufsize, flags )

They only problem is, sockets return socket objects via the accept
call. And the socket returned is of type socket, of course, not
new_socket, as I would like. I could override accept() to return a
new_socket, but I don't know how to convert the old socket to a new
socket. That is, I'd like to add a method to the class above something
like:

def accept( self ):
conn, addr = socket.accept()
<convert conn, which is type socket to type new_socket>
return ( conn, addr )

Does anyone have any suggestions on how to do the above?

 
Reply With Quote
 
 
 
 
Pelmen
Guest
Posts: n/a
 
      12-21-2005
imho:
class new_socket(socket):
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0,
_sock=None)
socket.__init__(self, family=AF_INET, type=SOCK_STREAM, proto=0,
_sock=None)

def accept( self ):
conn, addr = socket.accept()
return ( new_socket(_sock=conn), addr )

but i think your problem have a more simple way then inheritance

 
Reply With Quote
 
 
 
 
Maksim Kasimov
Guest
Posts: n/a
 
      12-21-2005

you have to agregate socket and the object must have "fileno" method,
thats gives a possibility to use instanses of your class with "select.select" function


class mySocket:

def __init__(self, ...):
self.__socket = None
...


def fileno(self):
return self.__socket.fileno()


def connect(self, __host, __port):
try:
self.close()
self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__socket.connect((__host, __port))
...


def close(self):
try:
if self.__socket is not None:
self.__socket.close()
finally:
self.__socket = None

...


http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> socket objects have a little quirk. If you try to receive 0 bytes on a
> blocking socket, they block. That is, if I call recv(0), it blocks
> (until some data arrives).
>
> I think that's wrong, but I don't want to argue that. I would like to
> create a subclass of socket that fixes the problem. Ideally, something
> like:
>
> class new_socket(socket):
> def recv( self, bufsize, flags=0 ):
> if bufsize == 0:
> return ""
> else:
> return socket.recv( bufsize, flags )
>
> They only problem is, sockets return socket objects via the accept
> call. And the socket returned is of type socket, of course, not
> new_socket, as I would like. I could override accept() to return a
> new_socket, but I don't know how to convert the old socket to a new
> socket. That is, I'd like to add a method to the class above something
> like:
>
> def accept( self ):
> conn, addr = socket.accept()
> <convert conn, which is type socket to type new_socket>
> return ( conn, addr )
>
> Does anyone have any suggestions on how to do the above?
>



--
Best regards,
Maksim Kasimov
mailto: (E-Mail Removed)
 
Reply With Quote
 
groups.20.thebriguy@spamgourmet.com
Guest
Posts: n/a
 
      12-21-2005
More simple way? What's that?

 
Reply With Quote
 
Steve Holden
Guest
Posts: n/a
 
      12-21-2005
(E-Mail Removed) wrote:
> socket objects have a little quirk. If you try to receive 0 bytes on a
> blocking socket, they block. That is, if I call recv(0), it blocks
> (until some data arrives).
>

Well, arguably you should just try to stop receiving zero bytes. Why on
earth is your application doing this?

> I think that's wrong, but I don't want to argue that. I would like to
> create a subclass of socket that fixes the problem. Ideally, something
> like:
>
> class new_socket(socket):
> def recv( self, bufsize, flags=0 ):
> if bufsize == 0:
> return ""
> else:
> return socket.recv( bufsize, flags )
>

That would indeed work, were it not for the complications you are about
to relate.

> They only problem is, sockets return socket objects via the accept
> call. And the socket returned is of type socket, of course, not
> new_socket, as I would like. I could override accept() to return a
> new_socket, but I don't know how to convert the old socket to a new
> socket. That is, I'd like to add a method to the class above something
> like:
>
> def accept( self ):
> conn, addr = socket.accept()
> <convert conn, which is type socket to type new_socket>
> return ( conn, addr )
>
> Does anyone have any suggestions on how to do the above?
>

You could use the "delegation" pattern - return an object that contains
a reference to the socket returned by accept(), and have that object
implement recv() as you outline above, and __getattr__() so that any
methods your socket *doesn't* implement are instead called on the socket
returned by accept().

There's a whole page of stuff at

http://aspn.activestate.com/ASPN/sea...&y=0&type=ASPN

but the best read will probably be

http://aspn.activestate.com/ASPN/Coo...n/Recipe/52295

In that article Alex talks about how old-style classes can't inherit
from basic Python types. This is out of date now for most types, but his
exposition of the principles of delegation remains a beacon of clarity.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

 
Reply With Quote
 
groups.20.thebriguy@spamgourmet.com
Guest
Posts: n/a
 
      01-13-2006
Steve,

To your question of why you'd ever receive value:

This is very common in any network programming. If you send a packet
of data that has a header and payload, and the header contains the
length (N) of the payload, then at some point you have to receive N
bytes. If N is zero, then you receive 0 bytes. Of course, you CAN
test for N == 0, that's obvious - but why would you if the underlying
layers worked correctly? Its just extra code to handle an special case.

 
Reply With Quote
 
groups.20.thebriguy@spamgourmet.com
Guest
Posts: n/a
 
      01-13-2006
Correction to my last post:

It should say:

"To your question of why you'd ever recv(0):"

 
Reply With Quote
 
Bryan Olson
Guest
Posts: n/a
 
      01-13-2006
(E-Mail Removed) wrote:
> To your question of why you'd ever [recv(0)].
>
> This is very common in any network programming. If you send a packet
> of data that has a header and payload, and the header contains the
> length (N) of the payload, then at some point you have to receive N
> bytes. If N is zero, then you receive 0 bytes. Of course, you CAN
> test for N == 0, that's obvious - but why would you if the underlying
> layers worked correctly? Its just extra code to handle an special case.


We need "extra code" around recv to ensure we get exactly
N bytes; 'recv(N)' can return less. The most straightforward
code I know to read exactly N bytes never passes zero to
recv (untested):


def recvall(sock, size):
""" Read and return exactly 'size' bytes from socket 'sock'.
Kind of the other side of sock.sendall.
"""
parts = []
while size > 0:
data = sock.recv(size)
if not data:
raise SomeException("Socket closed early.")
size -= len(data)
parts.append(data)
return ''.join(parts)


--
--Bryan
 
Reply With Quote
 
groups.20.thebriguy@spamgourmet.com
Guest
Posts: n/a
 
      01-14-2006
I don't think this is true in all cases - for example, if the protocol
is UDP, and the packet size is less than the MTU size. Although, I
could be wrong - I've always thought that to be the case.

I knew someone would have your response, that's why I earlier said I
didn't want to argue that.

But thanks for your comments.

 
Reply With Quote
 
Paul Rubin
Guest
Posts: n/a
 
      01-14-2006
(E-Mail Removed) writes:
> I would like to
> create a subclass of socket that fixes the problem.


The socket module is in a messy state right now and subclassing
sockets doesn't work for implementation-specific reasons besides the
issue you described. Take a look at socket.py to see the situation.

See also:

http://groups.google.com/group/comp....849013e37c995b
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Steve Holden Python 1 02-03-2009 06:20 AM
Re: socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Steve Holden Python 0 02-01-2009 12:45 PM
Re: socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Laszlo Nagy Python 0 02-01-2009 07:37 AM
socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Laszlo Nagy Python 1 01-27-2009 05:05 PM
Re: socket.unbind or socket.unlisten? - socket.error: (48,'Address already in use') Jean-Paul Calderone Python 0 01-27-2009 01:41 PM



Advertisments