2009年3月21日土曜日

boost::asio で pop3 (3)

 第3回目まで進んで、タイトルは「boost::asio の勘所」とでもした方が良かったか?と、後悔してます。なかなか pop3 の実装には入れません。前回は路線図を書いてみようという事でしたが、今回は通信における妙についてのお話です。

 async_write で、1024 byte 送信すれば、次の処理では、おそらく 1024 byte 送信された状態で処理が渡されると思いますが、受信に関しては、この事が全くあてはまりません。仮にクライアントとサーバの通信コードを両方とも自分が書いていても、途中の経路におけるルータの都合でパケットが分断されるかもしれないのです。また、相当昔の話になりますが、Flying XMODEM というのが流行った事があります。これは、受信をしたら ACK を返すという処理を、受信する前から先にACKを送信して転送速度を稼ごうというものでした。

 非同期IO処理における難しさの2点目は、指定した通りの送受信結果が反映されているという前提は成立しない点にあります。

 しかし、これらを補うフリー関数(普通の関数)があるので、これらを活用します。async_read, async_read_until 等が相当します。注意しなければならないのは、これらの関数は、指定した位置(状態)までを読むのではなく、条件を満たすまでキューの処理を繰り返すという点です。32 byte 読んでね!と指定したら、32byte以上を読んだ時点で指定した関数へ処理をリレーしますし、CL+LF まで読んでね!と指定したら、CR+LF の組が出現した時点で指定した関数へ処理をリレーします。相手の送信の仕方によっては、きっちり32byte のデータ長や、CR+LFまでのデータを受信するのではなく、次の段階のデータを受信している可能性もあるという事です。このため、async_read_until だけでは足りないと思って作成したのが getuntil です。

・・・続く

0 件のコメント: