asyncoreを使用したソケットバッファーの読み取り
質問
私はPythonが初めてで(Javaでプログラミングを何年も行っていますが)、単純なソケットベースのネットワークアプリケーションに取り組んでいます(ただの楽しみのため)。私のコードは、リモートTCPエンドポイントに接続し、サーバーからクライアントにプッシュされるデータをリッスンし、これに対して何らかの解析を実行するという考え方です。
サーバーからプッシュされるデータ->クライアントはUTF-8でエンコードされたテキストであり、各行は CRLF
( \ x0D \ x0A
)で区切られています。ご想像のとおり、クライアントがサーバーに接続し(ユーザーがキャンセルするまで)、その行を読み取って解析するという考え方です。
これをうまく機能させることはできましたが、これを正しい方法で行っているかどうかはわかりません。したがって、私の実際の質問(従うべきコード):
- これはPythonで実行する正しい方法ですか(つまり、これは本当に単純ですか)
- buffers /
asyncore
に関するヒント/トリック/有用なリソース(リファレンスドキュメントを除く)?
現在、データは次のように読み込まれてバッファリングされています:
def handle_read(self):
self.ibuffer = b""
while True:
self.ibuffer += self.recv(self.buffer_size)
if ByteUtils.ends_with_crlf(self.ibuffer):
self.logger.debug("Got full line including CRLF")
break
else:
self.logger.debug("Buffer not full yet (%s)", self.ibuffer)
self.logger.debug("Filled up the buffer with line")
print(str(self.ibuffer, encoding="UTF-8"))
ByteUtils.ends_with_crlf
関数は、 \ x0D \ x0A
のバッファーの最後の2バイトを単にチェックします。最初の質問が主要な質問です(回答はこれに基づいています)が、他のアイデア/ヒントは歓迎します。ありがとう。
解決
TCPはストリームであり、バッファに1つのメッセージの終わりと次のメッセージの始まりが含まれないことは保証されません。 そのため、バッファーの最後で\ n \ rを確認することは、すべての状況で期待どおりに機能しません。ストリームの各バイトをチェックする必要があります。
そして、非同期ではなくTwistedを使用することを強くお勧めします。 次のようなもの(メモリからは、すぐに動作しない場合があります):
from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver
class MyHandler(LineReceiver):
def lineReceived(self, line):
print "Got line:", line
f = protocol.ClientFactory()
f.protocol = MyHandler
reactor.connectTCP("127.0.0.1", 4711, f)
reactor.run()
他のヒント
さらに簡単です- asynchat とその set_terminator メソッド(およびそのモジュールの他の有用な情報)。 Twisted は数桁豊富で強力ですが、十分に単純なタスクの場合、asyncoreとasynchat(これらはあなたが観察し始めたように、スムーズに相互運用するように設計されています)実際に使用するのは非常に簡単です。