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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to