Adding idle timeout capabilities to asyncore

Giampaolo Rodola' gnewsg at gmail.com
Wed Oct 24 19:02:05 EDT 2007


On 23 Ott, 17:34, Josiah Carlson <josiah.carl... at gmail.com> wrote:
> On 22 Ott, 12:28, Giampaolo Rodola' <gne... at gmail.com> wrote:
>
>
>
>
>
> > Hi there.
> > We're talking about an asyncore-based server.
> > Just for the heck of it I'd like to set a timeout which will
> > disconnects the clients if they're inactive (i.e., no command or data
> > transfer in progress) for a long period of time.
> > I was thinking about putting the timeout value into an attribute:
>
> > def settimeout(self, secs):
> >      self.timeout = time.time() + secs
>
> > And then have the readable method call time.time() at every loop to
> > check if time has passed or not:
>
> > def readable(self):
> >     if time.time() >= self.timeout:
> >         self.send("Timeout")
> >         self.close()
> >     return 1
>
> > My only concern is if it's a good idea calling time.time() so often.
> > Since A LOT of clients could be connected simultaneously, couldn't it
> > be a too much resource-intensive operation?
> > I'd also be curious to know how Twisted implemented this kind of
> > stuff.
> > By calling time.time() at every loop?
>
> > Thanks in advance.
>
> Calling time.time() is relatively inexpensive in comparison to pure
> Python function calls, but indeed, it could be a bottleneck.
>
> I don't know what Twisted does, but what I would do is to add two
> variables to each instance of the class you want to add timeouts to;
> self.timeout and self.lastdata .  self.lastdata would hold the time
> for the last time you sent or received data on the socket, and
> self.timeout would hold the delay between when you last sent/received
> data and when it should be closed due to idle timeout.
>
> Now, since you are smart, you don't need to alter your handle_send()
> or handle_receive() methods in your asyncore subclass.  Instead, you
> rewrite asyncore.poll() to update .lastdata for every socket that is
> in either the reader or writer list, which will result in one
> time.time() call.  Further, to check for timeouts, you only ever need
> to check those sockets that are *not* in the readable or writable
> lists...
>
> To be precise, add the following block to your own copy of
> asyncore.poll just after the 'for fd in e:' block...
>
>         #handle timeouts
>         rw = set(r) + set(w)
>         now = time.time()
>         for f in (i for i in rw if i in map):
>             map[f].lastdata = now
>         for j in (map[i] for i in map if i not in rw):
>             if j.timeout+j.lastdata > now:
>                 #timeout!
>                 j.handle_close()
>
> You ARE going to need to initialize .timeout and .lastdata members for
> every instance, but that shouldn't be so bad (for a socket that
> doesn't time out, I would actually suggest a 1 hour or 1 day timeout).
>
>  - Josiah- Nascondi testo tra virgolette -
>
> - Mostra testo tra virgolette -

A really nice hack.
Thank you a lot, Josiah.




More information about the Python-list mailing list