2012-05-09 7 views
3

私はツイストで物事をする方法を学ぼうとしていますが、私はちょっとしたコンセプトに固執しています。基本的に2つの別々のフェーズで通信するプロトコルを作る:まず短いハンドシェイクと認証、実際の作業。Twistedでプロトコルの2つの異なるフェーズを分離する方法は?

def stringReceived(self, data): 
    if self.state == "authenticate": 
     handle_auth(data) 
    else: 
     handle_actual_work(data) 

私はこれを行うためのねじれた道を考え出す苦労しています:

私の素朴なアプローチは、このようなプロトコルを記述することです。上記は正常ですか?認証を行うプロトコルと認証されたクライアントのみを扱うプロトコルを書く方がはるかに理にかなっているようですが、どうすればそれができますか?

私は同様の質問Twisted: How can I identify protocol on initial connection, then delegate to appropriate Protocol implementation?を見ました。そこに与えられた解決策は、私の現在のアプローチと基本的に同じです。これは本当に適切なアプローチですか?

答えて

3

はい、あなたのバージョンはかなり正常です。おそらくTwistedはステートマシンのサポートを増やすべきです。なぜなら、これは一般的なパターンをさまざまなプロトコル、異なるイベントコンステレーションなどで内部的に100種類も実装しているからです。しかし、この部分は実際にTwistedの仕事ではありません。オブジェクトをネットワークに送信し、メソッドが呼び出されます(この場合はstringReceived)。あなたはそのメッセージで何をするかはあなたのオブジェクトに完全に依存しており、ifのステートメントはそれとは全く関係ありません:)。

このレベルでの質問は、実際には「ねじれた道」ではなく、文脈に依存する状態マシンとメソッドのPythonイディオムについてです。あなたのプロトコルの正確なニーズに応じて、あなたの現在のアプローチは罰金であってもよいし、次のような、特別な名前を持つメソッドに派遣する場合があります

def stringReceived(self, data): 
    getattr(self, "stringReceived_{}".format(self.state))(data) 

def stringReceived_authenticate(self, data): 
    if self.auth_ok(data): 
     self.state = 'normal' 
    else: 
     self.transport.loseConnection() 

def stringReceived_normal(self, data): 
    self.do_stuff(data) 

...あるいは手の込んだ取得し、あなたがかもしれませんデコレータ、メタクラスなどを使用したいこれらのアプローチには何も問題はありません。

+1

ツイストして新しいことは、あなたがそれを置くときに単純にパイソンの芝生にあるのとは対照的に、いくつかの本質的なツイストイディオムを逃しているのを知ることは本当に難しいかもしれません。そういうわけで、チャイムを経験した人にそのような治療ができるのです。ありがとう! – porgarmingduod

+0

なぜ関数名を文字列として保存し、すべての余分な作業をするのですか? 'self.state'にデータを処理する関数を格納するだけでなく、' self.state(data) 'を実行するのはなぜですか? – detly

関連する問題