2012-02-29 12 views
3

私は、Twistedを使ってTCPサーバーに接続するPythonプログラムを書いています。ソケットのもう一方の端にあるサーバーは、2つのプロトコル(protoAまたはprotoB)のいずれかを実行している可能性がありますが、接続を開始してどのプロトコルが使用されているかを「尋ねる」までは、中古。私は一度接続したプロトコル(protoAまたはprotoB)のバージョンを特定できますが、それは事前にわかりません。Twisted:最初の接続でプロトコルを識別し、適切なプロトコル実装に委譲するにはどうしたらいいですか?

明らかに、私のツイストプロトコル派生クラスには、特殊なコードがたくさんあることが明らかです。つまり、protoAがこのelifプロトを実行すると、何か他のことが行われます。しかし、2つの別々のプロトコルのコードを2つの別々のプロトコル実装に保持したいと考えています(基本クラスを通していくつかの機能を共有するかもしれませんが)。両方のバージョンのプロトコルには状態を維持する必要があるため、両方のバージョンを同じクラスにマッシュアップする必要があると混乱することがあります。

どうすればいいですか?おそらく、ファクトリ実装の最初の「プロトコル識別」ステップを実行し、次に正しいプロトコル派生をインスタンス化する方法はありますか?

答えて

4

プロトコルの実装全体で決定ロジックを混在させる代わりに、1か所に配置します。

class DecisionProtocol(Protocol): 
    def connectionMade(self): 
     self.state = "undecided" 

    def makeProgressTowardsDecision(self, bytes): 
     # Do some stuff, eventually return ProtoA() or ProtoB() 

    def dataReceived(self, bytes): 
     if self.state == "undecided": 
      proto, extra = self.makeProgressTowardsDecision(bytes) 
      if proto is not None: 
       self.state = "decided" 
       self.decidedOnProtocol = proto 
       self.decidedOnProtocol.makeConnection(self.transport) 
       if extra: 
        self.decidedOnProtocol.dataReceived(extra) 

     else: 
      self.decidedOnProtocol.dataReceived(bytes) 

    def connectionLost(self, reason): 
     if self.state == "decided": 
      self.decidedOnProtocol.connectionLost(reason) 

結局、あなたは少し少ない定型でこれを実装することができる場合がありますhttp://tm.tl/3204/

1

これは、簡単にいくつかの魔法で行われます。

class MagicProtocol(Protocol): 
    ... 
    def dataReceived(self, data): 
     protocol = self.decideProtocol(data) 
     for attr in dir(protocol): 
      setattr(self, attr, getattr(protocol, attr)) 

これは醜いですが、それは、事実選びだしプロトコルのための魔法のプロトコルを切り替えます。

関連する問題