4

「対話型」のク​​ライアント/サーバーの動作という適切な言葉がないため、Twisted を実行する方法について頭を悩ませてきました。

サービスに接続し、即時のクエリ/応答を実行する Protocol クラスと ClientFactory クラスのペアをまとめることができました (connectionMade -> self.queryStatus を参照)。これは期待どおりに成功し、Factory クラスからのサーバーの応答を出力します。

私の問題は、潜在的な着信データを常にリッスンしながら、データを送信する必要がある外部イベントがあることです。しかし、reactor.run() ループが実行されると、アプリケーションの残りの部分がデータ送信をトリガーする方法がわかりません。

それ以来、私はいくつかの異なるアプローチを試みましたが、これは、説明されているように recv 部分を処理した最も単純なアプローチです。

class myListenerProtocol(LineReceiver):
    delimiter = '\n'

    def connectionMade(self):
        print("Connected to: %s" % self.transport.getPeer())
        self.queryStatus(1)

    def dataReceived(self, data):
        print("Receiving Data from %s" % self.transport.getPeer())
        ...
        self.commandReceived(self.myData)

    def commandReceived(self, myData):
        self.factory.commandReceived(myData)

    def connectionLost(self, reason):
        print("Disconnected.")

    def queryStatus(self, CommandValue):
        ...
        strSend = CommandValue # or some such
        self.transport.write(strSend)

class mySocketFactory(ClientFactory):
    protocol = myListenerProtocol

    def __init__(self):
        pass

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

    def commandReceived(self, myData):
        print myData
        reactor.stop() # It won't normally stop after recv

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


def main():
    f = mySocketFactory()
    reactor.connectTCP("10.10.10.1", 1234, f)
    reactor.run()

これは非常に簡単なことだと思いますが、膨大な数の例とドキュメントに数え切れないほどの時間を費やしたため、このシナリオをどのように扱うべきかをよく理解できませんでした。

4

2 に答える 2

1

私の問題は、潜在的な着信データを常にリッスンしながら、データを送信する必要がある外部イベントがあることです。しかし、reactor.run() ループが実行されると、アプリケーションの残りの部分がデータ送信をトリガーする方法がわかりません。

「外部イベント」?どのような?接続でデータが到着しますか? リアクターを稼働させるということは、実際にそのデータを処理できるということです。

それとも、誰かが GUI のボタンをクリックしているのでしょうか? GUI 統合リアクタの 1 つを試してみてください。リアクタを実行するまで、これらのイベントを処理することはできません。

あなたはおそらく行き詰まっているでしょう、なぜならあなたはあなたの主な機能がやるべきだと思っていてreactor.run()、それから他のことをし続けるからです. これはそれがどのように機能するかではありません。イベント ドリブン プログラムを作成するときは、すべてのイベント ソースを定義し、それらのソースにイベントが到着したときに、イベント ループがハンドラーを呼び出すようにします。

于 2013-06-04T19:40:01.663 に答える
-1

それには多くのアプローチがあり、最適な方法は実際にはアプリケーションのコンテキストに依存するため、ここではこれを行う 1 つの方法について詳しく説明しませんが、最近ハッカーのニュースで読んだ記事にリンクします。

あなたが取り組んでいるものには当てはまらないかもしれませんが(または読んだことがあるかもしれません):

ところで、そのようなことを処理するのが得意な gevent や tornado を見たことがあるかもしれません。

他の「イベント」が GUI ツールキット (GTK や QT など) からのものである場合は、 GIL に十分注意してくださいコマンド ライン イベントだけが必要な場合でも、スレッドが必要であり、それでも注意が必要です。

最後に、より多くの対話を行いたい場合は、作業しているさまざまなユース ケース (GUI に接続する 1 つのクライアント、別のクライアントを CLI に接続する別のクライアント) と対話する、サーバー用のさまざまな種類の「ピア」を作成することもできます。 、データベースを使用する別、SAASのAPIを使用する別など..)。

つまり、デザインがうまくいかない場合は、視点を変えてみてください。

于 2013-06-04T18:29:57.893 に答える