投稿

パケ死

イメージ
先月(昨年)末、友人から中古で iPhone 6s を買い取り、ついに iOS デバイスのオーナーとなった。SIM を挿し替えて、Apple の移行ツールを利用して、ほとんどの設定が Android から自動で移行できた。だがその移行過程で、「モバイルデータ通信」を OFF にする間もなく、アプリのアップデートなどが始まり、数十秒後に気付いて処理を中断したものの、時すでに遅し……。数十秒で 89 MB のデータ通信が発生してしまった。 ドコモ口座を使いたいがためにドコモと契約してかれこれ 1 年と 2 ヶ月になっていたが、契約プランはカケホーダイで、パケット定額は契約せず、スマートフォン側でモバイルデータ通信を常時 OFF にすることによってこれまで何の問題もなく利用してきた。しかし、ほんの数十秒のミスで発生したわずか 89 MB のデータ通信に対するドコモの請求が、これ: 53,972 円 なんでパケット料金が何十年も前の携帯電話が主流の時代の単価のままなんだよっていう。 よく、総務省の有識者会議とかで携帯キャリアの規制について話題になってるけど、パケット単価の問題を放置して、他の何を会議で話し合っても、「何が有識者なの?」「何が国民の利益なの?」ちゃんちゃらおかしいと思う。 夜更ししていて寝る前の最後の一仕事のつもりでやったのがこういうことになって、ショックを受けたが、どうしようもないので、諦めて寝た。翌日、思い直して調べてみると、こういう事態が「パケ死」と呼ばれていることを知った。どちらかというと「パケ死」は、海外ローミングで発生する事態のようで、僕のように、意図的にパケット定額をしないで国内で普通に生活していて起こる事態は主流ではないようだ。 さらに、「パケ死」というキーワードをベースにして調べてみると、他にもこういう目に遭った人は少なくないようで、救済措置が存在することもわかった。ドコモの場合、一回だけ、遡って後付けでパケット定額に加入できるという。早速ドコモのインフォメーション(151)に電話してお願いし、最低額のパケット定額を適用してもらって、どうにか事なきを得た。 一度こういう事故に遭ってしまうと、たとえ以前より慎重に気を付けていたとしても、事故が起ってしまったらパケット料金が青天井であるということは恐しくて仕方がない。

HTTP/1.1 Transfer-Encoding: chunked

Web Scraping 用のプログラムを組んでいて、HTTP レベルの Socket プログラムを自前で組むか、Client レベルの処理は言語環境のライブラリーに任せて HTML を解析・処理する程度のものを組むかという、二択問題によく悩む。これまでの経験上、後者の方が敷居が低く取りかかるのに容易であるというメリットがある。一方、一旦何らかの壁にぶち当たると、ブラックボックスのない前者の環境で試行錯誤を進めた方が、心理的にもまさしく“急がば回れ”の典型のような結果となり、トータルで楽になる。 そんなわけで、今回取り組んでいる物件についても、スタートアップは Java の URLConnection で一通り組み上げてしまって、それで問題なく全体的に動くものが出来上がっていたので、そのまま運用していたものだった。ゼロ状態からのスタートとなるプロジェクトでは、まずはどんな形であれ、全体としてちゃんと動くものへと到達できるかどうかが不明な状態なので、「まずは全体としてちゃんと動くもの」まで辿り着くことが何よりも重要である。そのためには、Client レベルのものは Java のコアライブラリーに任せて、Web Scraping にターゲットを絞った方が確実にプロジェクトを成功まで推進することができる。 それでそのまま動くようになったままで運用し続けていて、プログラムには手を入れていなかったのだが、今度、Lanterna を使って GUI 化したりして、使い勝手が向上したので、さらに前から欲しいと考えていた機能を追加したりした。最終的には GUI 化したらしたで CUI の時は気にならなかった処理速度が気になったので、ネットワークからのデータの読み込みをマルチスレッド化するところまで行き着いた。 このネットワーク読み込み処理のマルチスレッド化で、ある問題が表面化したのだった。 どうやら Java の URLConnection は、スレッドセーフではないようなのだ。とはいっても、このプロジェクトに関して言えば、Cookie がスレッド間で共有されていることが問題の核心であり、それを URLConnection 自体がスレッドセーフではないという話に含めていいのかどうかはわからない。ともかく、Cookie が上書きされてしまうのが原因で、サーバー側が付与する JS

Exception の使い処

Perl では Exception のことは気にしないでプログラミングできたので、Java で当初特異に感じたのが Exception の扱いだ。仕様に強制される形で try-catch を行う必要があるという認識で今まで凌いできた。 そもそも CUI でプログラミングしている段階では、例外処理については別段の配慮はせずとも、コンソールに JVM が吐くエラーメッセージが表示されるので、自分でエラーに備える処理を明示的にコーディングする必要はなかった。CUI というのはそういった意味でユーザーとプログラマーが完全に同一レベルの視点で体験を共有しているので、ある意味貴重な環境なのかもしれない。 そういった CUI の貴重な環境の習慣をそのまま引き摺ってしまっていて、GUI で Android のアプリなどを作っていても、例外処理について、標準メソッド側が要求するから受動的に try-catch を記述する程度で、自分から能動的に Exception クラスを用いるという経験があまりなかった。 ところで最近 Web のフォーム送信操作を自動化する Java プログラムを作成していて、想定外のエラーが発生した時、そのエラーがどの段階で出たエラーなのかということがわかった方が、自分自身で利用するだけでなくもしアプリを公開するという前提では、その方が良いと考えた。そこで、各段階で、想定通りではない結果になっていた場合、Exception を発生させるようなコードにすることにした。 当初は字義的に、RuntimeException を使っていた。ところがこれでも「どの段階で発生したのか?」がわかりにくかったので、最終的には IOException を使うことに落ち着いた。 GUI ライブラリーとして Lanterna という ncurses ライクなライブラリーを使っており、コンソールではなく、GUI の表示にエラーメッセージも表示させたいと考えた。当初の RuntimeException だと、どこかでエラーが発生していることがコンソールには表示されるのだが、どの段階で起ったのかが把握しにくく、GUI 側でもどこでキャッチすればいいのかがわかりにくい。そこで IOException にして、GUI 側で catch させることにしたのである。 ネットワークにアク