2012-08-13 57 views
2

我有一個服務器,我已經實現了NetstringReceiver協議的一個孩子。我希望它根據客戶端的請求執行異步操作(使用txredisapi),然後用操作結果進行響應。我的代碼的推廣:Python twisted:異步操作後寫入連接的服務器?

class MyProtocol(NetstringReceiver): 
    def stringReceived(self, request): 
    d = async_function_that_returns_deferred(request) 
    d.addCallback(self.respond) 
    # self.sendString(myString) 

    def respond(self, result_of_async_function): 
    self.sendString(result_of_async_function) 

在上面的代碼,客戶端連接到我的服務器沒有得到迴應。然而,它得到的myString如果我取消

# self.sendString(myString) 

我也知道,result_of_async_function是一個非空字符串,因爲我把它打印到標準輸出。

我該怎麼做才能讓我用異步功能的結果來響應客戶端?

更新:可運行的源代碼

from twisted.internet import reactor, defer, protocol 
from twisted.protocols.basic import NetstringReceiver 
from twisted.internet.task import deferLater 

def f(): 
    return "RESPONSE" 

class MyProtocol(NetstringReceiver): 
    def stringReceived(self, _): 
    d = deferLater(reactor, 5, f) 
    d.addCallback(self.reply) 
    # self.sendString(str(f())) # Note that this DOES send the string. 

    def reply(self, response): 
    self.sendString(str(response)) # Why does this not send the string and how to fix? 

class MyFactory(protocol.ServerFactory): 
    protocol = MyProtocol 

def main(): 
    factory = MyFactory() 
    from twisted.internet import reactor 
    port = reactor.listenTCP(8888, factory,) 
    print 'Serving on %s' % port.getHost() 
    reactor.run() 

if __name__ == "__main__": 
    main() 
+0

不應該有'reactor.callLater(X,d.callback,...)'某處嗎? – 2012-08-13 20:09:38

+0

上面的代碼只是我認爲是相關部分。我有一個使用這個協議的工廠,我打電話給reactor.listenTCP(port,factory,)。 – 2012-08-13 21:18:19

+1

你能否更詳細地填寫這個例子?使其完成並可運行?你在這裏有正確的想法,這意味着問題在於細節,所以爲了回答你的問題,我需要看到具體細節。您可以使用'twisted.internet.task.deferLater'來模擬異步操作以進行演示。 – Glyph 2012-08-13 21:53:46

回答

2

有大約NetstringReceiver一個特定的功能:

如果接收到一個非法的消息

的連接丟失你確定你的消息符合djb's Netstring protocol

很顯然,客戶端發送了無法解析的非法字符串,並且連接因協議條件而丟失。 其他所有代碼在您的代碼中看起來不錯。

如果您不需要該特定協議,則最好繼承LineReceiver而不是NetstringReceiver

+1

感謝您的回答。如果一切都失敗了,我可能會重寫使用LineReceiver協議,但我還沒準備好放棄NetstringReceiver。我相當肯定我的問題與錯誤格式無關(我相信NetstringReceiver爲我處理格式)。就像我說的那樣,註釋掉的sendString確實有效,所以我相當確定它與我使用延遲的方式有關。我確實懷疑在延遲觸發之前連接正在關閉。 – 2012-08-13 20:39:16

+0

如果您使用的是sendString(並且從不transport.write),那麼'NetstringReceiver'應該爲您處理netstrings的語法。 – Glyph 2012-08-13 21:51:23

+0

所以我最終決定切換到LineReceiver,它工作。我仍然不確定爲什麼NetstringReceiver不工作,因爲我相當肯定我正確使用它。也許它是一個錯誤?注意:如果您使用lineReceiver,則應該使用telnet而不是netcat(由於分隔符問題) – 2012-08-16 15:47:41

0

您永遠不會收到回覆的原因是因爲在發送連接時關閉。連接關閉的原因是因爲您使用'nc'發送的消息是:
1:a,\n
因爲您必須鍵入換行符才能讓nc發送消息,但nc會將其作爲消息的一部分包含它。這違反了淨字符串協議... 我工作圍繞它(你的代碼有一些額外的照片修改)發送這個消息,而不是:
1:a,40:\n blahblahblah不要打回到這裏,只是等待答覆
8:RESPONSE,