Volevo scrivere un server a cui un client potesse connettersi e ricevere aggiornamenti periodici senza dover eseguire il polling. Il problema che ho riscontrato con asyncore è che se non si restituisce true quando viene chiamato dispatcher.writable(), si deve attendere fino a quando il tempo di asyncore.loop non è scaduto (il valore predefinito è 30s).Asyncore di Python per inviare periodicamente i dati utilizzando un timeout variabile. C'è un modo migliore?
I due modi in cui ho tentato di aggirare questo problema sono 1) ridurre il timeout a un valore basso o 2) connessioni di query per quando verranno aggiornati e generare un valore di timeout adeguato. Tuttavia, se si fa riferimento a "Select Law" in "man 2 select_tut", si afferma, "Si dovrebbe sempre provare a utilizzare select() senza un timeout."
C'è un modo migliore per farlo? Twisted forse? Volevo provare ed evitare discussioni extra. Io includo l'esempio timeout variabile qui:
#!/usr/bin/python
import time
import socket
import asyncore
# in seconds
UPDATE_PERIOD = 4.0
class Channel(asyncore.dispatcher):
def __init__(self, sock, sck_map):
asyncore.dispatcher.__init__(self, sock=sock, map=sck_map)
self.last_update = 0.0 # should update immediately
self.send_buf = ''
self.recv_buf = ''
def writable(self):
return len(self.send_buf) > 0
def handle_write(self):
nbytes = self.send(self.send_buf)
self.send_buf = self.send_buf[nbytes:]
def handle_read(self):
print 'read'
print 'recv:', self.recv(4096)
def handle_close(self):
print 'close'
self.close()
# added for variable timeout
def update(self):
if time.time() >= self.next_update():
self.send_buf += 'hello %f\n'%(time.time())
self.last_update = time.time()
def next_update(self):
return self.last_update + UPDATE_PERIOD
class Server(asyncore.dispatcher):
def __init__(self, port, sck_map):
asyncore.dispatcher.__init__(self, map=sck_map)
self.port = port
self.sck_map = sck_map
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(("", port))
self.listen(16)
print "listening on port", self.port
def handle_accept(self):
(conn, addr) = self.accept()
Channel(sock=conn, sck_map=self.sck_map)
# added for variable timeout
def update(self):
pass
def next_update(self):
return None
sck_map = {}
server = Server(9090, sck_map)
while True:
next_update = time.time() + 30.0
for c in sck_map.values():
c.update() # <-- fill write buffers
n = c.next_update()
#print 'n:',n
if n is not None:
next_update = min(next_update, n)
_timeout = max(0.1, next_update - time.time())
asyncore.loop(timeout=_timeout, count=1, map=sck_map)
Nick: Qual è la piccola modifica per farlo funzionare? Potresti inserire il codice? Grazie –