2014-01-27 81 views
3

我想實現一個自己的基於TCP的協議,用於Twisted之上的服務器。這種協議實現的機制很明確(繼承協議並覆蓋四個繼承的方法,建立Factory)。Python扭曲:從處理中分離協議

但是,我想我的協議爲從應用邏輯分離的,在一種方式:

  • 協議:從客戶端接收數據時,字節流進行解碼,並填充Python數據結構,需要的數據結構,編碼對字節流(基於文本的)並響應客戶

  • 應用邏輯:接收所述數據結構,計算和返回響應的數據結構

我該如何構建一個Twisted應用程序,它既不依賴於其他(即,鬆耦合)?我會想象協議類將被實例化一個應用程序邏輯回調作爲參數?

編輯:

在此期間,我有這樣的:

from twisted.internet.protocol import Protocol 
from twisted.internet.protocol import Factory 
from twisted.internet.endpoints import TCP4ServerEndpoint 
from twisted.internet import reactor 

class Logic: 
    def process(self, data): 
     return "Processed: %s" % data 

class LineProtocol(Protocol): 
    def dataReceived(self, data): 
     print "Received: %s" % data 
     if self.factory._logic_callback: 
      ret = self.factory._logic_callback.process(data) 
      print "Sent: %s" % ret 
      self.transport.write(ret) 

class LineFactory(Factory): 
    protocol = LineProtocol 

    def __init__(self, logic_callback = None): 
     if logic_callback: 
      self._logic_callback = logic_callback() 
     else: 
      self._logic_callback = None 

endpoint = TCP4ServerEndpoint(reactor, 1234) 
endpoint.listen(LineFactory(Logic)) 
reactor.run() 

你會認爲這是在 「扭曲」 的方式?任何需要改進的地方?

該代碼在LineFactory內創建一個Logic實例。很好把它放在那裏?

+0

到目前爲止你有什麼? – SingleNegationElimination

+0

「進程」是任何語言中使用任何庫的方法最糟糕的名稱之一。 –

+0

@ Jean-PaulCalderone:同意,請原諒我在這個示例中使用它。 – Bernd

回答

3

請注意,您的計劃中已經有一個鬆耦合的例子。處理TCP實現細節的傳輸與協議是分開的,兩個對象通過一個定義良好的接口進行交互:dataReceived et al on protocol,write et al on the transport。

只是將此想法延伸到另一個步驟。讓你的應用程序對象和協議通過一個定義良好的接口進行交互。應用程序對象是否作爲__init__參數被提供給協議有些取決於預期的交互作用。如果應用程序純粹是被動的(即它只對協議上發生的事情做出反應,它本身不會啓動),那麼這是一個好方法。如果應用程序對驅動動作更感興趣(例如,考慮驅動HTTP客戶端協議的應用程序:在應用程序決定發送請求之前,網絡上什麼都不會發生),那麼您可能需要明確定義一個接口爲了使協議具有應用程序預期使用的功能(例如,HTTP客戶端協議可能有一個採用URL,HTTP方法等的request方法)。

請記住,有一些很好的API可以讓您回到新的協議實例。例如:

from sys import argv 

from twisted.internet.protocol import Protocol 
from twisted.internet.endpoints import connectProtocol, clientFromString 
from twisted.internet.task import react 

def main(reactor, description): 
    endpoint = clientFromString(reactor, description) 
    connecting = connectProtocol(endpoint, Protocol()) 
    def connected(protocol): 
     # Now `protocol` is connected somewhere and you can start 
     # calling useful methods on it, if it has any. 
     ... 
    connecting.addCallback(connected) 
    return connecting 

react(main, argv[1:]) 

把一些有用的代碼爲connected,用你的更有趣的協議類的實例代替Protocol(),並與an argument like運行「TCP:本地主機:25」。

從你的例子:

def dataReceived(self, data): 
    print "Received: %s" % data 
    if self.factory._logic_callback: 
     ret = self.factory._logic_callback.process(data) 
     print "Sent: %s" % ret 
     self.transport.write(ret) 

這是不是真的有益。你還沒有在協議中實現任何協議邏輯。你所做的只是讓self.factory._logic_callback負責實施協議。這是一對額外的物體,沒有真正的好處。我不會建議這樣做。

你想在協議類中做所有的解析和序列化。只能委託更高級別的邏輯,用結構化對象(任何解析的輸出)來實現,而不是協議。