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