- Python 2.7
- Twisted 13.0
TCPクライアントを書く必要があったので調べ物。最初socketモジュールを使って書いたんだけど、Twistedを使うと簡潔に書けてリトライも簡単だったのでなんとなく。
やりたいこと
定期的にセンサデータを取得してTCPで外部へ送信を行えるハードウェアがある。これに対して接続し、受信したデータをロギング、任意の処理を行う。
サーバとなるハードウェアは認証や呼び出しなどが必要なプロトコルではなく、ひたすらデータ垂れ流すだけ。
書いてみる
protocol.py
import logging
from twisted.internet.protocol import Protocol
logger = logging.getLogger(__name___)
# プロトコルを処理するクラス
class SomeProtocol(Protocol):
def dataReceived(self, data):
logger.debug(u'data received. data: %s' % data)
# ログファイルに書き出し
f = open('log.dat', 'ab')
f.write(data)
f.close()
client.py
import logging
from twisted.internet.protocol import ReconnectingClientFactory
from .protocol import SomeProtocol
logger = logging.getLogger(__name___)
# クライアントクラス。実際に接続処理を行うのはこのクラス。
class SomeServerClient(ReconnectingClientFactory):
protocol = SomeProtocol
def buildProtocol(self, addr):
"""Procotolクラスのインスタンス生成メソッド
"""
logging.info(u'Successfully connected to %s' % addr)
self.resetDelay() # retry delayを元に戻す
protocol = self.protocol()
protocol.factory = self
return protocol
def startedConnecting(self, connector):
"""接続後に呼び出される
"""
logger.info(u'Started to connect.')
def clientConnectionLost(self, connector, reason):
"""接続を失った際のハンドラ
"""
logger.warning(u'Lost connection. Reason: %s', reason)
ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
def clientConnectionFailed(self, connector, reason):
"""接続に失敗した際のハンドラ
"""
logger.error(u'Connection failed. Reason: %s' % reason)
ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
実行してみる
reactorモジュールを使用してTCPサーバに接続する。
from twisted.internet import reactor
reactor.connectTCP('127.0.0.1', 5403, SomeServerClient())
reactor.run()
その他
Twistedあんまり速くないしgevent良いよって@masahifさんに教えてもらったので後で調べる。
今回は、単一のサーバと単一のクライアントで1秒おきに流れてくるデータを処理するだけなので速度を気にする必要がなくて、簡単にやりたいこと(リトライ処理)が書けたら良いのでTwistedで大丈夫そう。