2016-10-18 4 views
1

Ich möchte eine Art von Server haben, der Ereignisse empfängt (d. H. Mit Sockets), und jedes Ereignis hat eine andere ID (dst Portnummer).Python: Festlegen mehrerer kontinuierlicher Timeouts

Gibt es einen Weg, dass von dem Moment an, wo ich das erste Paket einer bestimmten ID sehe, ich eine Art Timeout (dh 1ms) starte, und wenn in dieser Zeit nichts anderes mit der gleichen ID empfangen wird ausgelöst, aber wenn etwas empfangen wird, wird das Timeout auf 1 ms zurückgesetzt.

Ich habe gesehen, dass so etwas mit signals und dem SIGALARM Signal getan werden kann. Ich möchte jedoch mehrere "Timer" für jede unterschiedliche ID behalten.

+0

Mögliche Duplikat [Python: Laufen mehrere Timer gleichzeitig] (http://stackoverflow.com/questions/26446110/python-running-multiple-timers-simultaneously) –

+0

Was Ich will, ist anders, in den Antworten geben sie nur ein Beispiel dafür, wie man eine Funktion nach X-Zeit mit 'threading.Timer' ausführt. Ich möchte auf einige Ereignisse warten, bis ein Ereignis nicht nach 1 ms zum Beispiel erscheint, aber dann immer noch auf die anderen Ereignisse lausche und nicht "abgelaufen" – edgarstack

Antwort

2

Klingt wie ein Job für select. Da Sie Sockets verwenden, haben Sie einen Socket-Deskriptor für einen Client (vermutlich einen für jeden Client, aber solange Sie einen haben, funktioniert es). Sie möchten also entweder warten, bis ein Paket in einem Ihrer Sockets ankommt, oder bis ein Timeout auftritt. Genau das tut select.

berechnen also die Ablaufzeit für jeden Client, wenn Sie eine Nachricht erhalten, dann in der Hauptschleife, einfach berechnen die am ehesten verfallen Timeout und sehen vor, dass als timeout Parameter select.select (mit allen Socket-Deskriptoren wie die rlist Parameter). Dann werden Sie geweckt, wenn ein neues Paket/Nachricht ankommt oder wenn das älteste Timeout abläuft. Wenn es sich um ein neues Paket handelt, verarbeiten Sie das Paket und setzen das Zeitlimit des Providers auf 1 ms zurück. Andernfalls tun Sie, was auch immer Sie tun, wenn das Zeitlimit abgelaufen ist.

Berechnen Sie anschließend das Zeitlimit für die Zeitüberschreitung. Spülen. Schaum. Wiederholen.

Etwas wie folgt aus:

now = time.time() 
timeout = min([(client.expiration - now) for client in clients_list]) 
rrdy, wrdy, xrdy = select.select([client.sock for client in clients_list], [], [], timeout) 
if not rrdy: 
    # Timeout 
    now = time.time() 
    for client in clients_list: 
     if client.expiration < now: 
      process_timeout(client) 
else: 
    # Process incoming messages 
    for rsock in rrdy: 
     process_message(rsock.recv(4096)) 
     client.expiration = time.time() + .001 
+0

Ich denke, das sollte funktionieren, aber vielleicht habe ich Probleme, wenn zu viele Operationen dazwischen liegen, nein? Da Timeout so klein ist. – edgarstack

1

Siehe das integrierte Modul sched, das über einen Scheduler verfügt.

Sie können eine neue Scheduler-Instanz erstellen und dann mit scheduler.enter eine Funktion planen, die nach einer Verzögerung aufgerufen wird. und wenn Sie innerhalb des Zeitlimits eine Nachricht erhalten, können Sie das Ereignis mit aus der Warteschlange entfernen. Sie können scheduler.run() verwenden, um den Scheduler in einem anderen Thread auszuführen, oder Sie können scheduler.run(blocking=False) in einem Select-Multiplexing-Thread mit Timeouts verwenden.

+0

Können Sie Ereignisse in den Scheduler eingeben, während er läuft? Weil ich jedes Mal, wenn ich eine Veranstaltung bekomme, absagen und neu eingeben muss. Wird das gut funktionieren, wenn ich Ereignisse von 1000 Ereignissen der gleichen Zeit (was bedeutet, dass ich jedes Mal einen neuen Timer abbrechen muss) in 10ms erhalte. Theoretisch kommen alle Ereignisse des gleichen Typs zusammen, aber ich weiß nicht, wann ich sie alle empfangen sollte, also muss ich überwachen, wenn ich sie für eine gewisse Zeit nicht empfange. – edgarstack