Hatena::ブログ(Diary)

hnwの日記 このページをアンテナに追加 RSSフィード

[プロフィール]
 

2014年8月24日(日) PHPでHTTPの並行ダウンロードを実現する(Guzzle編) このエントリーを含むブックマーク このエントリーのブックマークコメント

PHPで最近注目のHTTPクライアントライブラリGuzzleがあります。日本での知名度はまだまだという印象ですが、かなり高機能かつ真面目にメンテナンスされている印象で、今後のデファクトスタンダードになりうるライブラリと言えるでしょう。


本稿ではこのGuzzleを使ってWebサーバから並行にダウンロードする方法を紹介します。Webブラウザのように同時に複数コネクションを管理しながらKeep-Aliveでコネクションを使い回しますので、下手なコードで実現するより接続先Webサーバにも優しいはずです。


Guzzleの特徴

まずは、Guzzleについて僕が特徴的だと思う点を紹介します。



欠点は巨大すぎることと、マニュアル日本語訳がまだ無いことくらいでしょう。


Guzzleのバージョン

Guzzleを使う上で、Guzzleのバージョンには要注意です。GuzzleにはGuzzle 3とGuzzle 4と2つのバージョンがあります。同じ機能でもGuzzle 3とGuzzle 4とでメソッド名が変わっていたりするので、検索で見つけた記事を読むような場合は注意してください。


Guzzle 3とGuzzle 4は異なるネームスペースを利用していますので、どちらを使っているかは一目瞭然です。Guzzle 3の名前空間は「\Guzzle\」から始まり、Guzzle 4は「\GuzzleHttp\」から始まります。


また、Packagistでのパッケージ名もGuzzle 3は「guzzle/guzzle」、Guzzle 4+は「guzzlehttp/guzzle」となっていますので、composer.jsonに書く際も注意が必要です。


Guzzle 4は今年の3月にリリースされたばかりですが、今から使うならこちらを使った方が良いでしょう。本稿でもGuzzle 4を利用しています。


並行ダウンロードするサンプルコード

Guzzleの一般的な使い方は他のページを見て頂くとして、早速並行ダウンロードのサンプルコードを紹介します。このコードはジェネレータを使いたかったのでPHP 5.5以降でしか動作しませんが、Guzzle 4はPHP 5.4以降で動くはずです。

続きを読む

トラックバック - http://d.hatena.ne.jp/hnw/20140824

2014年8月9日(土) PHP 5.4.4から==の挙動が一段と難しくなりました このエントリーを含むブックマーク このエントリーのブックマークコメント

PHPの==は両辺を適当に型キャストしてから比較するような演算子です。この型キャストの規則は難解すぎる上にドキュメントも不十分なため、PHPプログラマでも完璧に理解している人はほとんど居ないくらいの印象です。バグの原因になりかねないため、なるべく==を使わないようにしているPHPプログラマも多いはずです。


ところで、この==演算子の挙動がPHP 5.4.4から変更されていることはあまり知られていません。本稿ではこの内容を紹介します。


Bug #54547 の騒動

まずはこの仕様変更の経緯を紹介します。


2年ほど昔、Hacker News2^63付近の整数に対応する文字列をPHPで比較したときの挙動がおかしいというスレッドが盛り上がったことがありました。具体的には、PHPでは「'9223372036854775807' == '9223372036854775808'」がtrueになるという話題で、PHPの仕様をDISるような流れでした。


僕のように古くからのPHPユーザーにとっては==の挙動がキモいことは常識ですし、この例で浮動小数点数比較されているのも一目瞭然、他の言語の人が叩きに来るのも日本ではよくあることで、海外も周回遅れで同じ流れになってるのかなーというくらいの印象でした。僕からするとこれは仕様ですし、==の実装は複雑すぎて整合性を保ちつつ不満を解消するような仕様変更は不可能だと感じていたため、いくら叩かれようが修正はありえないと思っていました。


ところがPHP中の人がムシャクシャしていたのか何なのかはわかりませんが、これをバグとして修正する流れになりました。そのバグ報告と修正までの流れは「PHP :: Bug #54547 :: wrong equality of string numbers」で確認することができます。これがPHP 5.4.4から取り込まれており、今回紹介する内容ということになります。


PHP 5.4.4での変更内容

PHP 5.4.4からは、上で紹介した'9223372036854775807' == '9223372036854775808'」がfalseを返すようになっています。


この変更の詳細についてマニュアルなどには記述が見当たりませんが、ソースパッケージの./UPGRADINGに次のように書いてあります。


Long numeric strings that do not fit in integer or double (such as

"92233720368547758070") are compared using string comparison if

they could otherwise result in precision loss - since 5.4.4.


翻訳すると次のようになります。


整数浮動小数点数におさまらないような巨大な数値文字列("92233720368547758070"など)を比較する場合に、

文字列比較しないと精度が落ちるような場合には文字列比較が使われます。(PHP5.4.4から)


そもそも言葉足らずなのですが、これは数値文字列同士を比較する場合の話題です。PHP 5.4.3以前では数値文字列同士を比較する場合はかならず整数または浮動小数点数にキャストされてから比較されていました。しかし、キャストで精度が落ちるような数値文字列同士の場合は文字列比較するよ、というのがPHP 5.4.4での変更ということになります。


説明のため、64bit環境のPHP 5.5.11での実行例を示します。

続きを読む

norinori 2014/08/10 14:14 騒ぐ理由が分かりませんね。

hnwhnw 2014/08/10 14:49 特に分かっていただく必要は無いのですが、もし僕がこのコードを業務でコードレビューしたとすれば、何かしらコメントすると思います。普段のお仕事の内容が違うのかもしれませんね。

eighteight 2014/08/10 15:55 ソースコード読んで細かい事にネチネチ言ってるほうがよっぽどキモいと思う
チミが問題だと思うならバグレポなりなんなりして本家に反映させたほうがよっぽど有意義だよ

DSHDSH 2014/08/10 15:57 そもそも精度が怪しい数値をイコールで比較すること自体が間違ってるし、
バージョン上げるためにいちいちソース確認しなきゃなんないような
タイトな設計ならPHPなんて使わずにフルスクラッチで書くってば。

てゆっか、bccomp()でいいんでない?

hnwhnw 2014/08/10 17:33 eightさん:
ソフトウェア技術者にとってソースコードこそ最強の1次情報源だと思いますが、ソースコード読む奴キモいとか言う人が技術者を名乗ってるとしたら楽しい業界ですね。

DSHさん:
確かにサンプルコードのようなコードを書くことはまずありえないでしょう。しかし、==同様の比較はin_array関数やsort関数でも行われるので、同様の処理を書いてしまう可能性はゼロではないはずです。PHPプログラムを読み書きする仕事であれば、==の挙動を把握しておくことは重要だと思います。

また、OSSを採用する上でいざとなったらソースを確認する気概は重要だと僕は思います。そのコストが非現実的だと思うならプロプライエタリ製品を使うべきでしょう。たとえPHPを使わなかったとしても、コンパイラにもOSにもバグはありえます。

eighteight 2014/08/10 18:50 ソース読むことがキモいなんてただの一言も言ってない。
粗探ししてはdisるだけで俺phpソース読んでてかっこいいだろ、ってのが言いたいことなのがキモい。
ソースコード読めるのに日本語が読めないとしたら楽しい世界ですね

hnwhnw 2014/08/10 18:53 eightさん:
一応断っておくと、僕は日本人の中ではかなりPHPのバグレポ書いてる方ですよ。30件くらいですけど。パッチも採用されてる。で、あなたは?

DSHDSH 2014/08/10 23:47 まー、そこらへんは概ね同意。
部下がそんなコード書いてたら小一時間問い詰めるとこなんだけど、
ソフトウェア資産(笑)が地雷抱えてることは多々あるんで。

hnwhnw 2014/08/11 10:40 本体のソースコード読んだりバグレポ書いたりパッチ送ったりだけがcontributionじゃないし、そうしないと使えないなんてことも無いはずですが、本体のソースコードをもっと皆がカジュアルに読んだ方が各個人にとっても世界にとってもプラスになるんじゃないかなーと僕は思ってます。念のため補足でした。

トラックバック - http://d.hatena.ne.jp/hnw/20140809

2014年7月5日(土) GitHubユーザーのSSH鍵6万個を調べてみた このエントリーを含むブックマーク このエントリーのブックマークコメント

GitHub APIを利用して、GitHubの31661アカウントに登録されているSSH公開鍵64404個を取得してみました。抽出方法*1が適当すぎて偏りがあるような気もしますが、面白い結果が得られたと思うのでまとめてみます。

SSH鍵の種類

鍵の種類 個数 割合
RSA 61749 (95.88%)
DSA鍵 2647 (4.11%)
ECDSA鍵 8 (0.01%)

約6万個の鍵のうち、8個だけECDSA(楕円DSA)鍵が見つかりました!常用しているのか試しに登録してみただけなのかはわかりませんが、何にせよ意識高い感じでステキですね。


SSH鍵のbit長

RSA
鍵長 個数 割合
800bit 1 (0.00%)
1024bit 2034 (3.29%)
1026-2046bit 15 (0.02%)
2048bit 58773 (95.18%)
2050-4094bit 25 (0.04%)
4096bit 827 (1.34%)
4098bit- 74 (0.12%)

2048bit鍵が多数派という結果になりました。これは多くのSSH実装がデフォルトで生成する鍵長だと思うので、当然の結果ではあります。


1024bit鍵の人もボチボチ見つかります。最短の鍵長はなんと800bitでした。あとで触れますがよろしくないですね。

続きを読む

*1GitHubのユーザID1番から1万番、100万番から101万番、…800万番から801万番の人のうちSSH鍵を登録している人の全ての公開鍵を先月末に取得しました

matokenmatoken 2014/07/07 21:26 2/10に試した時はECDSA(ecdsa-sha2-nistp256)は弾かれてしまいました><
なので多分GitHubがECDSAに対応したのが最近でそのため登録者が少ないのではないかと思います.
現在もed25519はダメですね

hnwhnw 2014/07/08 08:20 なるほど、そんな最近に対応したんですね。てっきり保守的な人が多いのかと思ってました。Ed25519鍵への対応も待たれますね。

2014年6月29日(日) Console Componentを利用したメモ このエントリーを含むブックマーク このエントリーのブックマークコメント

Console Componentを使った感想を記録しておきます。雑なメモですが、どなたかの参考になれば。


Console Componentとは

Console ComponentはPHPコマンドラインアプリケーションライブラリです。コマンドラインオプション解析や、出力に簡単に色をつける機能などを提供しています。


ちなみに、このライブラリSymfony Componentsに含まれています。SymfonyPHPの有名フレームワークですが、多くの機能をスタンドアロンライブラリとして切り出しています。Console Componentもその一つということになります。


コマンドラインオプション解析ライブラリとしての特徴

  • 標準的なコマンドラインオプションに対応している
    • short option/long option両対応
    • 値を取らないshort optionを圧縮して指定できる(-v -a -xを-vaxと指定できる)
    • オプションが値を取らない/値が必須/値を指定してもしなくても良い/複数指定できるに対応
  • サブコマンドに対応している
  • ヘルプメッセージ(--helpで出力される内容)を勝手に作ってくれる
  • テストが書きやすい

イマイチな点

  • コマンドラインオプション解析だけしたい場合には巨大かつ冗長
    • 必ずCommandクラスを継承したクラスを作らなくてはならない
  • サブコマンド無しのコマンドが標準では作れない
    • 単機能のツールを作る場合でも必ずサブコマンド指定をさせることになる
  • --with-foo,--without-fooのようなオプション指定に標準で対応していない
    • 他言語の同等ライブラリでは真偽値を返してくれるものがあって便利
  • 値を取るオプションの場合に、型の指定ができない

上記のうちいくつかは簡単に対応できそうな気もしていますが、「巨大かつ冗長」はどうにもならんと思います。


サンプルコード

以下、Commandクラスを継承したクラスの例です。これをApplicationクラスからadd()で登録して使います。

続きを読む

DQNEODQNEO 2014/07/24 15:01 参考になります。

Console_CommandLine はcomposerでインストールできますし。
名前空間がない(アンダーバー区切り)こと以外は悪くないのではないでしょうか。
https://github.com/pear/Console_CommandLine

hnwhnw 2014/07/24 15:34 DQNEOさん:
言われてみればそうですね。PEARと聞くだけでPEAR_Errorの呪いを思い出してしまって拒絶反応を出す病気にかかっていたんですが、Console_CommandLineを見直してみると十分使い続けられそうですね。
ですから、コマンドライン解析ライブラリとしてのConsole Componentの利点があるとすれば、テストのしやすさという点くらいかと思います。下記URLのように、ApplicationTesterを通じてコマンドラインオプションを与えたり、出力を文字列として取り出したりできますので、コマンドラインオプションを含めたテストが書きやすい印象です。
https://github.com/hnw/FizzBuzz/blob/master/tests/FizzBuzzTest.php

トラックバック - http://d.hatena.ne.jp/hnw/20140629

2014年6月10日(火) RSA鍵の生成時に確率的素数判定法を使って問題ないのか このエントリーを含むブックマーク このエントリーのブックマークコメント

前回記事「RSA公開鍵から素数の積を取り出す方法」でも紹介しましたが、RSA鍵の生成には巨大な2つの素数p,qが必要です。近年一般的に使われている2048bit鍵の場合なら、p,qの大きさは1024bit、10進で約308桁の数になります。


このRSAアルゴリズム中ではpとqを法としたフェルマーの小定理(正確にはその拡張であるオイラーの定理)を利用しています。つまり、pとqが合成数だとRSA暗号の大前提が狂ってしまいますので、pとqには確実に素数を選ぶ必要があります。


ところで、OpenSSLRSA鍵生成の実装では、pとqの素数判定にMiller-Rabin素数判定法を用いています。Miller-Rabin素数判定法は片側誤りの確率的アルゴリズムで、「たぶん素数」「確実に合成数」の判定ができるようなものです。pとqの素数性が重要なのに、その判定に確率的アルゴリズムを使っても問題ないのでしょうか?


合成数のp,qでRSA鍵を作ってみる

ものは試しで、合成数のp,qでRSA鍵を作ってみましょう。OpenSSLRSA鍵生成の実体はbn_prime.cのBN_generate_prime_ex関数にあります。

続きを読む

トラックバック - http://d.hatena.ne.jp/hnw/20140610
 
ページビュー
1169505