1

私は、これらの新しい「工場」スタイルのネットワーク ライブラリについて自分なりの方法を学ぼうとしています。Twisted には多くの称賛が寄せられていますが、ラムダに詳しくなく、デモ コードが何を行っているかを理解する方法がよくわからないため、私にとっては絶対的な悪夢です。

デモ クライアント:

from twisted.internet import reactor, defer
from twisted.internet.protocol import ClientCreator
from twisted.protocols import amp
from ampserver import Sum, Divide


def doMath():
    d1 = ClientCreator(reactor, amp.AMP).connectTCP(
        '127.0.0.1', 1234).addCallback(
            lambda p: p.callRemote(Sum, a=13, b=81)).addCallback(
                lambda result: result['total'])
    def trapZero(result):
        result.trap(ZeroDivisionError)
        print "Divided by zero: returning INF"
        return 1e1000
    d2 = ClientCreator(reactor, amp.AMP).connectTCP(
        '127.0.0.1', 1234).addCallback(
            lambda p: p.callRemote(Divide, numerator=1234,
                                   denominator=0)).addErrback(trapZero)
    def done(result):
        print 'Done with math:', result
    defer.DeferredList([d1, d2]).addCallback(done)

if __name__ == '__main__':
    doMath()
    reactor.run()

デモサーバー:

from twisted.protocols import amp

class Sum(amp.Command):
    arguments = [('a', amp.Integer()),
                 ('b', amp.Integer())]
    response = [('total', amp.Integer())]


class Divide(amp.Command):
    arguments = [('numerator', amp.Integer()),
                 ('denominator', amp.Integer())]
    response = [('result', amp.Float())]
    errors = {ZeroDivisionError: 'ZERO_DIVISION'}


class Math(amp.AMP):
    def sum(self, a, b):
        total = a + b
        print 'Did a sum: %d + %d = %d' % (a, b, total)
        return {'total': total}
    Sum.responder(sum)

    def divide(self, numerator, denominator):
        result = float(numerator) / denominator
        print 'Divided: %d / %d = %f' % (numerator, denominator, result)
        return {'result': result}
    Divide.responder(divide)


def main():
    from twisted.internet import reactor
    from twisted.internet.protocol import Factory
    pf = Factory()
    pf.protocol = Math
    reactor.listenTCP(1234, pf)
    print 'started'
    reactor.run()

if __name__ == '__main__':
    main()

私が理解しているように、クライアントp.callRemote(Sum, a=13, b=81)p.callRemote(Divide, numerator=1234, denominator=0)部分はMath.sum(13, 81)andMath.Divide(1234, 0)を呼び出します。これは、ファクトリ オブジェクトがクラスprotocolに設定されているためです。Mathどういうわけか、クライアントがサーバーから戻り値を受け取ると、サブ関数Done(result)が呼び出され、画面に内容が出力されます。

これは素晴らしいことですが、私の理解力は最悪で、すべてのドキュメントはすでにこのレベルの理解を期待しているようです。

私が本当にできるようにしたいのは、クライアントからサーバーへ、およびサーバーから接続されている複数のクライアントへデータを送信することです。このメソッドは、交換が終了するとすぐにクライアントを忘れるように見え、クライアントをreactor.run()ブロックし、他の作業を実行できなくなります。

人々はおそらく毎日この機能を望んでいます。どうすればこれを理解できますか?

編集:クライアントが呼び出すための「チェックイン」機能を用意しようとしましたが、「報告するものはありません」と応答するだけで、サーバーがリクエストで溺れてしまうようです。また、クライアントが新しいデータを実際に利用可能になったときではなく、要求したときにのみ受信するという点で、遅延が追加されます。ファクトリ - リアクター レイアウトは、任意に応答するために保存する必要があるクライアント情報を公開していないようです。

4

1 に答える 1

1

次の 3 つの質問があるようです。

  1. lambdaパイソンでどういう意味?」

    これはPython のドキュメント でカバーされています。それでも、この方法で書かれたコードを読むのに苦労している場合は、それlambda x: yが単なる近道であるという事実を利用できますdef my_function(x): return ylambdaたとえば、次のようなが表示されている場所:

    def foo(bar):
        return boz().addCallback(lambda result: qux(bar, result))
    

    lambda次のように、読みやすくするために、いつでも を独自の関数に引き出すことができます。

    def foo(bar):
        def callback_for_boz(result):
            return qux(bar, result)
        return boz().addCallback(callback_for_boz)
    
  2. ある接続での入力を別の接続での出力にするにはどうすればよいですか?

    これはTwisted の FAQ に記載されています。

  3. " Twisted を複数のクライアントと通信させたり、複数のサーバーに接続するにはどうすればよいですか? "

    これもねじれた FAQです。ここでの一般的な考え方は、reactor.run()「...そしてプログラム全体を実行する」という意味です。以前にコードを実行する唯一の理由reactor.run()は、初期タイマー、リッスン ソケット、または最初の接続を設定するためです。connectTCPorlistenTCPは、reactor を実行する前、またはプログラムの後半で発生するコールバックで、好きなだけ呼び出すことができます。

于 2012-10-24T21:37:55.823 に答える