2016-10-18 41 views
1

我想要某种类型的服务器接收事件(即使用套接字),并且每个事件都有不同的ID(即dst端口号)。Python:设置多个连续超时

有没有一种方法,从我看到特定ID的第一个数据包的那一刻起,我开始某种超时(即1ms),并且如果在那段时间内没有收到其他具有相同ID的事件,被触发,但如果收到某些事件,超时重置为1ms。

我已经看到类似的东西可以通过使用signalsSIGALARM信号来完成。但是,我想为每个不同的ID保留多个“计时器”。

+0

的可能的复制[Python中:运行多个同时定时器(http://stackoverflow.com/questions/26446110/python-running-multiple-timers-simultaneously) –

+0

什么我想要的是不同的,在答案中他们只给出了一个例子,说明如何在X时间之后使用'threading.Timer'执行一个函数。我想要监听一些事件,直到一个事件不会在1ms后出现,但仍然在监听其他正在到达并未“过期”的事件 – edgarstack

回答

2

听起来像是select的工作。当你使用套接字时,你有一个客户端的套接字描述符(大概每个客户端都有一个套接字描述符,但只要你有一个套接字描述符,它就可以工作)。所以你要么等待一个数据包到达你的某个插座,要么等到超时发生。这正是select所做的。

所以计算的到期时间为每个客户端,当您收到一条消息,然后在你的主循环,简单地计算,最快到过期超时,并提供为timeout参数select.select(所有的插座描述为rlist参数)。然后,当新的数据包/消息到达或最旧的超时过期时,您会被唤醒。如果是新数据包,则处理数据包并将该提供程序的超时值重置为1ms;否则,你在超时过期时做任何事情。

然后计算下一个到期超时。冲洗。泡沫。重复。

事情是这样的:

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

我认为这应该有效,但如果两者之间的操作太多,我可能会遇到问题,不是吗?由于超时很小。 – edgarstack

1

查看sched内置模块,它有一个调度程序。

您可以构造一个新的调度器实例,然后使用scheduler.enter来调度在延迟后调用的函数;如果您在时间限制内收到消息,则可以使用scheduler.cancel(event)从队列中删除其事件;您可以使用scheduler.run()在另一个线程中运行调度程序,也可以在具有超时的选择多路复用线程中使用scheduler.run(blocking=False)

+0

您可以在运行时将事件输入到调度程序中吗?因为每次收到活动时都必须取消并重新输入。如果我在10毫秒内收到同一事件的1000个事件(这意味着我必须每次取消并输入一个新的计时器),这样做的表现会不错吗?从理论上讲,所有同类型的事件都会聚集在一起,但我不知道何时应该考虑所有这些事件,所以我必须监视我什么时候没有收到它们。 – edgarstack