1

I want to have some kind of server that receives events (i.e using sockets), and each event has a different ID (i.e dst port number).

Is there a way that from the moment I see the first packet of an specific ID, I start some kind of timeout (i.e, 1ms), and if in that time nothing else with the same ID is received an event is triggered, but if something is received the timeout is reset to 1ms.

I have seen that something like that can be done by using signals and the SIGALARM signal. However, I want to keep multiple "timers" for every different ID.

2
  • Possible duplicate of Python: Running multiple timers simultaneously Commented Oct 18, 2016 at 19:23
  • What I want is different, in the answers they only give an example of how to execute a function after X time using threading.Timer. I want to be listening for some events until one event does not appear after 1ms for example, but then still listening for the other events that are arriving and did not "expired" Commented Oct 18, 2016 at 19:28

2 Answers 2

2

Sounds like a job for select. As you are using sockets, you have a socket descriptor for a client (presumably one for each client but as long as you have one, it works). So you either want to wait until a packet arrives on one of your sockets or until a timeout occurs. This is exactly what select does.

So calculate the expiration time for each client when you receive a message, then in your main loop, simply calculate the soonest-to-expire timeout and provide that as the timeout parameter to select.select (with all the socket descriptors as the rlist parameter). Then you get awakened when a new packet/message arrives or when the oldest timeout expires. If it's a new packet, you process the packet and reset that provider's timeout to 1ms; otherwise, you do whatever you do when the timeout expires.

Then calculate the next-to-expire timeout. Rinse. Lather. Repeat.

Something like this:

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
Sign up to request clarification or add additional context in comments.

1 Comment

I think that should work, but maybe I have problems if there are too many operation in between, no? Since timeout is so small .
1

See the sched built-in module, which has a scheduler.

You can construct a new scheduler instance, then use scheduler.enter to schedule a function to be called after a delay; and if you receive a message within the time limit, you can remove its event from the queue using scheduler.cancel(event); you can use the scheduler.run() to run the scheduler in another thread, or you can use scheduler.run(blocking=False) in a select-multiplexing thread with timeouts.

1 Comment

Can you enter events into the scheduler while is running? Because I have to cancel and enter it again every time I receive an event. Will this perform well if I receive events 1000 events of the same time (which means I have to cancel and enter a new timer every time) in 10ms. In theory all the events of the same type come together, but I don't know when to consider them all received so I have to monitor when I dont receive them for a period of time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.