select.select and socket.setblocking
Francesco Bochicchio
bockman at virgilio.it
Tue Dec 30 13:19:08 EST 2008
Laszlo Nagy ha scritto:
> I'm using this method to read from a socket:
>
> def read_data(self,size):
> """Read data from connection until a given size."""
> res = ""
> fd = self.socket.fileno()
> while not self.stop_requested.isSet():
> remaining = size - len(res)
> if remaining<=0:
> break
> # Give one second for an incoming connection so we can stop the
> # server in seconds when needed
> ready = select.select([fd], [], [], 1)
> if fd in ready[0]:
> data = self.socket.recv(min(remaining,8192)) # 8192 is
> recommended by socket.socket manual.
> if not data:
> # select returns the fd but there is no data to read
> -> connection closed!
> raise TransportError("Connection closed.")
> else:
> res += data
> else:
> pass
> if self.stop_requested.isSet():
> raise SystemExit(0)
> return res
>
>
> This works: if I close the socket on the other side, then I see this in
> the traceback:
>
> File "/usr/home/gandalf/Python/Projects/OrbToy/orb/endpoint.py", line
> 233, in read_data
> raise TransportError("Connection closed.")
> TransportError: Connection closed.
>
> Also when I call stop_requested.set() then the thread stops within one
> seconds.
>
> Then I switch to non blocking mode, my code works exactly the same way,
> or at least I see no difference.
>
> I have read the socket programming howto (
> http://docs.python.org/howto/sockets.html#sockets ) but it does not
> explain how a blocking socket + select is different from a non blocking
> socket + select. Is there any difference?
>
> Thanks
>
Couple of remarks:
1. AFAIK, select in python accepts also socket objects, or anything
which has a fileno() method returning an integer. So you don't need to
extract the fileno from the socket (python will do for you) although it
does no harm.
2. IMO, the behaviour of your code is correct: with TCP protocol, when
the remote ends disconnects, your end receives a 'read event' without
data; you should just handle the fact that recv returns nothing as
normal, not as error, and close your end of the connection.
If you are interested in socket errors, you should
also fill the third 'fd-set' in the select call, and after select
returns check that fd is not in it anymore:
ready = select.select( [fd],[], [fd] )
if fd in ready[2]:
# raise your error here
3. AFAIK (sorry, I feel acronym-ly today ;), there is no difference in
select between blocking and non-blocking mode. The difference is in the
recv (again, assuming that you use TCP as protocol, that is AF_INET,
SOCK_STREAM), which in the blocking case would wait to receive all the
bytes that you requested, or the disconnection, in the other case would
return immediately (and you should check the number of returned bytes,
and when you read the remaining bytes of the message put the pieces
together). I myself tend to avoid using non-blocking sockets, since
blocking sockets are much easier to handle...
HTH
Ciao
------
FB
More information about the Python-list
mailing list