2013-06-02 61 views
2

客戶:雙絞協議實例變量?

#!/usr/bin/env python 

from twisted.internet import reactor, protocol 

class EchoClient(protocol.Protocol): 
    def __init__(self, arg): 
     self.arg = arg 

    def connectionMade(self): 
     self.transport.write("hello, world!") 

    def dataReceived(self, data): 
     print "Server said:", data 
     self.transport.loseConnection() 

    def connectionLost(self, reason): 
     print "connection lost" 

class EchoFactory(protocol.ClientFactory): 
    protocol = EchoClient 

    def buildProtocol(self, address): 
     proto = protocol.ClientFactory.buildProtocol(self, address, 12) 
     self.connectedProtocol = proto 
     return proto 

    def clientConnectionFailed(self, connector, reason): 
     print "Connection failed - goodbye!" 
     reactor.stop() 

    def clientConnectionLost(self, connector, reason): 
     print "Connection lost - goodbye!" 
     reactor.stop() 

def main(): 
    f = EchoFactory() 
    reactor.connectTCP("localhost", 8000, f) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

SERVER:

#!/usr/bin/env python 

from twisted.internet import reactor, protocol 
from twisted.application import service, internet 

class Echo(protocol.Protocol): 
    def dataReceived(self, data): 
     self.transport.write(data) 

def main(): 
    factory = protocol.ServerFactory() 
    factory.protocol = Echo 
    reactor.listenTCP(8000,factory) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

錯誤:

exceptions.TypeError: buildProtocol() takes exactly 2 arguments (3 given) 

問題:

我怎樣才能在CLIENTEchoClient類接受參數並給實例變量(例如在上面的構造函數EchoClient中)?如下所述,先前建議我重寫buildProtocol函數,但是我這樣做的嘗試已導致我出現上述錯誤。我不確定該從哪裏出發。我想我的問題可以概括爲:如何將實例變量添加到協議?

回答

7

你寫道:

def buildProtocol(self, address): 
    proto = protocol.ClientFactory.buildProtocol(self, address, 12) 

就是要覆蓋ClientFactory.buildProtocol,並用不同的簽名調用父類比它知道如何處理。

從工廠傳遞數據到客戶端只是有點棘手。您可以提供任何想要出廠的__init__,但扭曲會自行創建IProtocol的實例。幸運的是,大多數工廠分配自己的協議的factory屬性,一旦它已經準備好去:

class MyClientProtocol(protocol.Protocol): 
    def connectionMade(self): 
     # use self.factory here: 
     self.transport.write(self.factory.arg) 

class MyClientFactory(protocol.ClientFactory): 
    protocol = MyClientProtocol 

    def __init__(self, arg): 
     self.arg = arg 

事實上,整個ProtocolFactory業務是支持這種使用;但要小心; Protocol的許多實例將共享其工廠的單個實例;使用工廠配置但在協議中管理狀態

協議/工廠實現的標準系列不適合您的需求,這也是合理的,只要您完全實現了IProtocolIProtocolFactory接口即可。基類的存在是因爲它們爲你處理大多數情況,並不是因爲它們是唯一可能的實現。

+0

謝謝!這似乎工作得很好! – rarify

+0

爲了記錄,這是一個很好的答案! :) – jathanism

1

這不是從你的問題不清楚是什麼究竟你tryed什麼究竟的誤差,但無論如何你必須做兩步:

  1. EchoClient的構造帶你需要的任何參數它需要並初始化您需要初始化的任何字段。
  2. 在您的工廠中重寫buildProtocol方法將這些參數提供給您的協議。