twistedをさわってみる

pyapnsのソースを追っかけてたんだけど、どうも読みにくい。
これは多分使われているtwistedについて何も知らないからだ。
せっかくだから入門してみよう。

ということでよく見かけるEchoサーバーを書いて動かしてみた

# coding=utf-8
from twisted.internet import protocol, reactor
from twisted.internet.protocol import connectionDone


class UpperEcho(protocol.Protocol):
    """クライアントとデータの処理
    """

    def dataReceived(self, data):
        print self.transport.__class__
        # => <class 'twisted.internet.tcp.Server'>
        self.transport.write(data.upper())

    def connectionMade(self):
        print 'connectionMade: connected'

    def connectionLost(self, reason=connectionDone):
        print 'connectionLost connected'
        print reason
        # => [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
        # ]


class UpperEchoFactory(protocol.Factory):
    """クライアントの接続とプロトコルの管理
    """

    def buildProtocol(self, addr):
        print addr
        # => IPv4Address(TCP, '127.0.0.1', 54956)
        return UpperEcho()


if __name__ == '__main__':
    reactor.listenTCP(1234, UpperEchoFactory())
    reactor.run()

コンソールからtelnet localhost 1234で接続でき、タイプした文字のuppercaseが表示される

以下メモ

1. reactor.listenTCPにポート番号とprotocol.Factoryを継承したクラスのインスタンスを渡す
Factoryは「クライアントの接続とプロトコルの管理」を行う。


2. 接続がくるとFactoryのbuildProtocolが呼ばれ、protocol.Protocolを継承したクラスのインスタンスを返す
attrには接続元情報を保持しているインスタンスが渡されるようだ


3. Protocolのインスタンスを作成する際に、クライアントに接続し、接続後にconnectionMadeが呼ばれる


4. telnetに入力をするとdataReceivedが呼ばれる
Protocolが保持しているtransportはtwisted.internet.tcp.Serverのインスタンスでこいつのwriteメソッドに文字列を渡すことでクライアントにレスポンス、この場合はuppercaseを返せる


5. コンソール側で接続を切るとconnectionLostが呼ばれる
reasonという引数が渡されるが、printしてみると以下のような文字列だった

[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
        # ]

なんかエラーっぽいようなエラーっぽくないような。。正常に接続が切れたと思ってよいのだろうか