让twister服务器采取主动

时间:2011-09-20 16:07:20

标签: python twisted

我有一台服务器处于扭曲状态,实现LineReceiver协议。 当我在响应客户端消息时调用sendLine时,它会立即将该行写入客户端,正如人们所期望的那样。

但是说客户要求服务器进行冗长的计算。我希望服务器定期向客户端发送进度消息。当服务器主动调用sendLine而客户端没有要求任何内容时,它似乎等待客户端在发送任何内容之前向服务器发送消息。

如何在没有客户明确要求的情况下立即从服务器向客户端发送消息?

3 个答案:

答案 0 :(得分:2)

如果异步执行计算,请使用延迟 其他方式,如果它是在单独的线程中的一些长计算,开始由让我们说deferrToThread(),使用reactor.callFromThread()
(我假设我们不在主循环中进行繁重的计算 - 这非常非常错:)) 小例子:

def some_long_foo(data_array, protocol):
    def send_msg(msg, protocol):
        # It actually looks petter in classes without pushing protocol here and
        # there
        protocol.transport.write(msg)

    for n, chunk in enumerate(data_array):
        do_something_cool(chunk)
        if n and (n % 10 == 0):
            from twisted.internet import reactor
            # here send_msg will be safely executed in main reactor loop
            reactor.callFromThread(send_msg, '10 more chunks processed',
                                   protocol)

# Somwhere in lineReceived we start long calculation
def cb(result):
    self.transport.write('got result: {}'.format(result))
d = threads.deferToThread(some_long_foo, data_array, self)
d.addCallback(cb)

因此,现在我们将通知客户处理每10个数据块,然后最终发送给他结果。 代码可能有点不正确,只是例如

docs

<强> UPD: 只是为了澄清: 错过了sendLine部分。一般来说没关系,把它称为transport.write()

答案 1 :(得分:1)

您可以随时使用sendLine发送一行,它应该立即到达,但您可能遇到与服务器阻止相关的问题。

sendLine的调用被推迟,因此如果您在一堆处理过程中进行调用,则可能暂时没有执行任何操作,然后当收到消息时,反应器中断处理,接收消息,并在返回处理之前获取排队的消息。您应该在此处阅读其他一些答案,并确保您的处理不会阻塞主线程。

答案 2 :(得分:0)

如果“立即”表示“客户端连接时”,请尝试在sendLine子类的LineReceiver中调用connectionMade