金色のMacProが手元に届くという夢を見た
Introduction
夢の話をしようと思う。
MacOSXは僕が過去6年にわたって慣れ親しんできたOSだ。システムは隅から隅まで直感的だし、シンプルかつ必要十分な機能が実現されている。比較的短い期間でアップデートされることで数百もの新機能が追加され、Macはより理想的なコンピューティングに近づく。それはユーザーにとって革新の連続。MountainLionにおいても、OSレベルでソーシャルメディアとのシームレスな連携が実現しているし、細部まで行き届いたジェスチャーの滑らかさ、通知センターというユーザーフレンドリーな機能などが追加されている。MountainLionは、iPhoneで培ったAppleの美学がMacOSXに結実した瞬間だ。それは他の追随を許さない快適さをもたらし、私達の生産性を高めているのだ。アップデートされる度にまったく新しい体験をもたらしてくれるAppleに心を奪われるのは当然のことのように思う。MacOSXは生活を極彩色へと導く強さと美しさを兼ね備えたOSだ。それはまるで、魔法のような存在なのだ。とはいえ、Macは高い。高性能なマシンを買えば20万程度にはなってしまう。すこしばかり貧しい私達も、スターバックスでドヤ顔くらいしたいものだ。
私が見た夢について
今から話すことは、すべて夢の話だ。Macのボディカラーは美しい銀色であり、断じて金色であってはならない。私は日常的に虚言癖があり、しばしば人の迷惑となっているようなので、今回もそのつもりで聞いて頂きたい。
深い霧の中を、一頭の獅子が歩く。
鬣は薄く禿げ上り、痩せこけた姿は幾分みすぼらしくも見えるが、当の本人は存外なんとも思っていないらしい。霧の中を静かに、しかし重々しく進んでいくその様子は、誇り高き山獅子として貫禄を存分に感じさせていた。山獅子とはいえども獅子であることに変わりなく、どうやら百獣の王としてこの里山に君臨しているようだ。
ここで私は一度夢から醒める。そして考えるのだ。「果たして鬣すらないようなただの獅子が、本当に百獣の王として相応しいのか?」と。ましてや山獅子。何度も反芻しても返ってくる答えは「否」であった。また、こうも思う。「あの貫禄と霧の中を歩くその造形の美しさ、これだけは確かである。あれは山獅子などではなく、私の見当違いだったのではないか。」などと考えているうちに、私はまた夢の中へと誘われていく。
時に残月、光冷ややかに、山獅子が岩壁に姿を見せる。荒涼とした岩壁には野草一つ茂ることもなく、周囲にはこの禿げ上がった獣がいるのみである。獣は、東の空に向かって吠える。
東雲も終わりの刻である。やがて地平線より朝の光が里山を照らし始め、照らされるのはこの山獅子とて同様である。山獅子の痩せこけた体を覆う体毛に、一気に光が差し込んでいく。反射した体毛の眩しさに、思わず顔を背ける。
気がつくと、私が先日組み上げた金色の機械に獅子が鎮座していた。私は驚きながらも、その状況を驚くほど自然に受け入れており、このようなことを考えていた。「そうか、この獅子は山獅子であると同時に、実のところ金獅子でもあったのだ。光りに照らされたその毛は、鬣の有無に関わらず何よりも美しい。金獅子こそが百獣の王たりえる存在なのだ。」
私はどうやら未だ夢の中にいるようだ。夢のなかに登場する山獅子について、具体的に語ろうと思う。
OSx86
さて、山獅子は如何にして私の元にやってきたか。OSx86については以下の通りだ。
OSx86を実践するためにお世話になったサイトがこちら。日本語の資料もなくはないが、ここが圧倒的に充実してる。Tonyさんの存在なくして山獅子を手懐けることは難しい。
Hardware
OSXを走らせるためには、特定のハードウェア構成が必要となる。インストール可能な構成や相性については英語ドキュメントになるがTonyさんのブログに任せるとして、私の環境では以下の通りである。
- Intel core-i7 3770K
- nvidia GEFORCE GT640
- Patriot Memory DDR3 PC3-12800 8GB × 4
- Intel SSD 335SEROES 240GB
- GIGABYTE B75M-D3H
ここで重要なのは、CPUとグラフィックボード、マザーボードである。逆に言えば、この3つさえ対応するものを揃えれば基本的にインストール不可、ということはない。このあたりもTonyさんの記事を熟読のこと。
MountainLionのインストール
大まかなフローとしては、普通にappstoreで山獅子を購入、USBメモリにUniBeastおよびMultiBeastというアプリケーションを入れ、MountainLionをUSBに入れる。BIOS設定でUSBブートを行い、MountainLionをインストールする、といった流れになる。とはいえ、ご察しの通りそんなにうまくいくはずがない。UniBeastがbootdiscの用意を、MultiBeastがドライバの用意をしてくれる。
- Purchase the OS X Mountain Lion Application from the Mac App Store
- 適当なMacを用意するか誰かから借りるかしてappstoreにログイン、普通に買いましょう
- Prepare a UniBeast USB flash drive
- USBメモリは8GBか16GBが望ましい。UniBeastはtonyさんのところにいってもらってくる
- Tonyさんのサイトで会員登録が必要
- UniBeastを起動するとよしなにやってくれる
- USBメモリは8GBか16GBが望ましい。UniBeastはtonyさんのところにいってもらってくる
- Install OS X Mountain Lion
- Install the bootloader and drivers using MultiBeast
- UniBeastおよび山獅子を入れたUSBには、同時にMultiBeastというアプリケーションも入れておく必要がある。これもTonyさんのところから頂いておく
ハマりどころ
さて、無事OSXのインストールが終了したと思いきや、戦いはこれからである。そもそもハードウェアが謹製のマシンと全然違うのだから、サウンドやネットワークなど、とにかくデバイスにまつわる機能が使えない。そこで役に立つのがMultiBeastなのだが、こいつが厄介だった。奨励されるドライバを入れて再起動しても、WhiteScreenになってしまいOSXが起動しない、諦めてOSを一から再インストールという手順を10回近く行った。とはいえ、MultiBeastのお陰でサウンド、ネットワーク、グラフィクスに関わるドライバは問題なくインストールできたことは併記しておく。
問題になったのはスリープである。デバイスをインストールしても、スリープをしたら最後、二度と目覚めない状態だったのだ。
スリープを実現する
起動やスリープは、OSがBIOSに含まれるDSDTテーブルを読むことで実現している。OSXの場合、特定のハードウェア構成で起動することを前提としているので問題ないのだが、今回行うOSx86では大問題である。OSが読むハードウェア情報が間違っているためにWhiteScreenや起動失敗といったことが起こる。Linuxでも起きそうだと思っていたら、案の定あるらしい。
DSDTテーブルの取得方法はMacのコマンドやUbuntuのLiveCDを使う方法などがあるが、今回はDSDTSEというツールを用いた。正常起動、デバイスの認識、スリープの実現を目指すためには、結局のところ以下の手順が正解だった。
- スリープをめざす順序
- multibeastでドライバをいくつか入れる
- サウンド、ネットワーク、ブートローダ
- 最後にDSDTSEをつかってextractしたDSDTテーブルをインストール明示的に示す
- multibeastのuserDSDTが間違っているため
- ブート時のconfigファイルである/Extra/org.chameleon.Boot.plitを変更
- multibeastでドライバをいくつか入れる
<key>GraphicsEnabler</key> <string>no</string>
- ここまでの間に再起動してはいけない
一連の手順を踏まえた上で再起動を行い、正常起動ができたらほとんど安心していい。ドライバの名称や画面などは以下に貼ったスクリーンショットを参照のこと。
終わり
これで私は獅子を手懐けることに成功した。備忘録およびこれを読むどなたかの参考になれば幸いだが、あくまで夢の話であって、私の妄言に拠っていることだけは留意していただきたい。
PCを新調しました
もはや1年以上「PCがほしい、PCがほしい」とツイートし続けてきたが、今回ついに新しいPCを新調する運びとなった。今までMacBook(late 2006)という化石のようなPCで戦ってきたわけだけれど、開発者の端くれとしていつまでも貧弱なハードウェア構成のマシンを使うわけにはいかない(白目 加えて、学生時代と異なりPCを外に持っていく機会もほとんどないので、大きなディスプレイに見合ったパワフルなデスクトップPCを1から構築することにした。私が出す要件は以下の通りである。
基本方針
高性能なモデルがほしい
- CPU
- 私のMacBookは、一時代を築いたintel Core 2 duoだった。当時はあまりの速さに感動していたが(その前はamdの廉価モデルの何かを使っていた記憶)、時代の進歩とは残酷なもので、Sandy世代のCPUを搭載した職場のMacBookProを常用するようになってからは不満が募るようになってしまった。どうせ買い換えるのならばIvy世代の最新CPUにしようと思う。
- メモリ
- グラフィクス
- ストレージ
極端な大型化を避ける
- 「なんなんだ、これは...」
- 先日まで、自作PCを組むべきか、MacMiniの上位モデルを買うべきか悩んでいた程度には小型のマシンがほしいと考えていた(しかも新型のMacMiniなら2.6GHzのクアッドcore-i7が78000円とMacにしてはそれほど高くない)。多少の大きさは構わないのだが、秋葉原電気街諸店舗における自作PCのケースコーナーに溢れているような、独特のカルチャーをもった、厨二病というか、「これが俺のマシンや!どやぁ!(LEDで光を帯びたファン「ファンファン」)」みたいなセンスには我慢ならなかったし、何よりあの灯油ケースみたいなサイズが許せない。僕の家は狭いし、ものが多い。自作するのなら、大きさはそこそこに、値段は多少かかってもいいので圧倒的にハイセンスなケースを探すべきだと判断した。
FYI : http://blog-imgs-46.fc2.com/m/o/t/motobuyer45/cosmos22.jpg
- 拡張性や排熱
予算はできれば10万以下
- 悪くないスペックのMacMiniが8万(カスタマイズ入れて10万)で買えるのにわざわざ自作するとなったら、それを超えるスペックで10万以下に抑えたい。とはいえ、今回はコンピュータの勉強的側面もあったのでそこまで気にしない。
ハードウェア構成
お待ちかね、今回このようなわがままな要望を満たす運びとなったハードウェア構成が以下のとおりだ。費用も合わせて明記しておく
- CPU : i7 3770k
- GPU : nvidia GEFORCE GT640
- MSI \6,480
- RAM : 32GB
- Patriot Memory DDR3 PC3-12800 8GB × 4 \9,940
- Storage : SSD240GB + HDD300GB
- OS : windows8 + fuckOSX
- Motherboard : GIGABYTE micro-ATX
- GIGABYTE B75M-D3H \5,980
- PowerSupplyUnit : 玄人志向
- KRPW-P2-650W/85+ \6,480
- ODD
- 謎に満ちた光学ドライブ \1,744
- Case
- abee AS Enclosure ASE-LP210 \19,980
- Trackpad
- Apple MagicTrackpad \6,800
- その他
合計して11~12万程度になるかと思う。ケースが2番目に高い買い物になっている。無駄にケースにお金をかけているし、windowsOSやtrackpadまで購入しているので少し足がでてしまったが、全く問題ない。
ちなみに、これが今まで使ってきたMacBookの技術仕様だ。 http://support.apple.com/kb/SP23?viewlocale=ja_JP&locale=ja_JP
知人の世話になりつつ、実際に組んでみる。マシンとして組む過程や、何度もBIOSを確かめることでコンピュータがどのように動いているのか少なからず理解できたように思う。問題なく起動することができたが、今回windows8はHDDにインストールした。HDDだから多少の遅さがあるとはいえ、動作している。今のところ、音や熱が問題になっている感覚はない。非常に静かで、安定した様子を見せている。
出来上がり
ケース
これが私の探し求めていた、自作PC界隈の文化とは一線を画すセンスフルなケース。黒やシルバーの先行く、ゴールド。金は上質の象徴だ。ケースから黄金の金が鳴っているのが写真で伝えられないのが遺憾である。
全容。完成されたボックスの造形である。これがほんとの、黄金比や!
オーディオ機器としての存在感もばっちりである。これを使うユーザーはまったく新しいGoldExperienceに打ちのめされること請け合いだ。
音・映像
- オーディオ機器に関しては、ソニーの標準サイズのコンポを出力として利用している。音質に関しては既に10年以上前からあるものなのでなんともいえないが、そのあたりの数千円程度のPCステレオよりはよいと思われる。
- 映像に関しては、DELLの23インチフルHDをそのまま利用している。補助ディスプレイとして、32インチの東芝REGZAをHDMIで繋いでいる。以外と問題なく表示できており、GPUのお陰か動画も美しく描画されるので満足である。
スコア
さて、今回組んだPCがどれ程のパフォーマンスを持つのか、試しにテストしてみようと思う。Geekbench2というアプリケーションを用いて測定してみた。測定結果は以下の通りだが、これは32bit版として測っているので、実際にはもっとスコアが高く出るような気もする。
ちなみに往年のMacBookのスコアはこちら
新しいPCが64bitであることを加味すると、ほとんど5倍かそれ以上の速度にはなっているようです。メモリが32GBある安心感が素晴らしい。動画を見ながらIDEどころか、動画を見ながら動画が見れるのではないでしょうか!これでHuluドリブンな開発ができますね!(白
まとめ
- ぱそこん組むって楽しいですね
- 積極的に厨二病になろう!
- 黄金のケースこそ至高
- OSまわりの設定は次エントリ
- 時代の進歩とは
- 6年間使った黒いMacBookには愛着がある
”To be C or not to be C. That is the question.”
半年くらい経ったのでそこそこにまとめる
身につけたこと/今後の展望
身につけたこと、とはいえどれも中途半端だし、自信を持って「できます」といえるレベルは程遠い。上限が見えないからこそ面白くはあるんだけど、みんなどこまでやって「できます」って言えるようになるんだろう...
- UNIX/Linuxの基本的な操作
- 簡単なシェルスクリプトくらいなら
- コンピュータに対する理解が甘いので、もっといじる
- Webアプリケーションへの理解
- テスト
- あまり学べていない
- JavaでSelenium2を使った自動テストをやった程度
- HTML/CSS
- 卒なく組めるようにはなった
- classやname,idの付け方が下手くそ
- CSSの修正にめちゃくちゃ時間がかかる
- floatやalign属性への理解不足
- PHP/template engine
- まあまあ書けるようにはなった
- オブジェクト指向関連の処理系についてまだ良くわかっていない点が多いので、1つずつ潰していく
- javascript
- フリーダム言語なのでとりあえず動くようにはできるけど、まだ全然言語仕様についての理解が足りない
- 言語仕様だけでなく、DOM操作、ライブラリについても学ぶ必要がある
- これらを切り分けて理解していくのが大事
- Database
超ざっくりかつカテゴライズ適当過ぎるけど、こんなものだろうか。んで、次。
今後身につけたいこと
今まで学んできたことの理解を更に深めることに加え、いわゆるスクリプト言語とは別のものをちゃんと学んでおきたいな、と思っている。なぜなら実際にプログラムを実行するコンピュータについてや、プログラムが動く仕組みなどへの理解が足りていないからだ。限られたリソースの中で厳格なコードによって処理が行われる一連の動作、ミニマルな形で学ぶことができる低級言語がいいと思っている(これとは別だが、関数型言語も学びたい)。あと、普段使っているフレームワークの内部実装などを積極的に調べて、コードをちゃんと読む機会を増やしたい。というわけで、今は「新しいサービスを世の中に出したい!」みたいな意識が全然なくて、こんなに意識が低くてよいものかと若干不安ではある。
- 今までの理解を更に深める
- コンピュータ・ネットワーク・セキュリティ全般
- 「なぜ動くのか」シリーズを片っ端から読むといいかもしれない
- 「効率的なWebアプリ~」とかっていう本とか
- UNIX/Linux
- PHP/HTML/CSS/javascript
- 今後も経験積んでいきましょう
- 公式ドキュメントに目を通すようにしましょう
- パーフェクトjavascript読みましょう
- コンピュータ・ネットワーク・セキュリティ全般
- 新しく勉強したいこと
- なにか言語1つ
- 低級言語
- 関数型言語
- コードを読む機会を増やす
- その他
だらだら羅列したものの、今はこれに尽きる。
「C言語を学ぶべきか、死ぬべきか。それが問題だ。」
『フカシギの数え方』 おねえさんといっしょ! PHPで数えてみよう!
おねぇさぁぁぁぁぁん! 日本科学未来館のアニメに狂気が宿っていると話題に
http://nlab.itmedia.co.jp/nl/articles/1209/11/news104.html -ねとらぼ
日本科学未来館のアニメがあまりにも面白かったので触発されて書いてみました。間違ってる可能性も大いにありますので、その辺生暖かい目で見てください。英語で探せばもっといいコードが出てくると思います。
class Explode { private $x = 0; private $y = 0; private $size = 0; private $dest = 0; private $line = array(); function __construct($arg) { $this->size = (int)$arg; $this->x = (int)$arg - 1; $this->y = (int)$arg - 1; for ($i = 0; $i < $this->size; $i++) { for ($j = 0; $j < $this->size; $j++) { $this->line[$i][$j] = 0; } } } function setGoOn($x, $y) { $this->line[$x][$y] = 1; } function walk($x, $y) { $this->line[$x][$y] = 1; if ($x == $this->x && $y == $this->y) { $this->dest++; } else { if ($x < $this->size -1 && $this->line[$x + 1][$y] === 0) { $this->walk($x + 1, $y); } if ($x > 0 && $y < $this->size -1 && $y != 0 && $this->line[$x - 1][$y] === 0) { $this->walk($x - 1, $y); } if ($y < $this->size - 1 && $this->line[$x][$y + 1] == 0) { $this->walk($x, $y + 1); } if ($y > 0 && $x > 0 && $x < $this->size - 1 && $this->line[$x][$y - 1] === 0) { $this->walk($x, $y - 1); } } $this->line[$x][$y] = 0; } function getCount() { return $this->dest; } } $arg = intval($argv[1]) + 1; $oneisan = new Explode($arg); $oneisan->setGoOn(0, 0); $oneisan->walk(1, 0); echo $oneisan->getCount() * 2;
実行してみる。
ちゃんとおねえさんの数えた通りの数字になっていますね!
ただ、おねえさんと違って私たちは手近なところにスーパーコンピューターなんてあるはずがないので5x5か6x6が限界だと思います(5マスのときは20秒くらいかかりました)。
さもないと「あれから25万年がたった・・・」なんて話になるので、実行はお気をつけて!
githubに置いときます
HTTPってなんなの 2/2
※第2回目
前半はこちら
http://d.hatena.ne.jp/arerreee/20120821/1345568635
さて、前回はHTTPプロトコルの概要およびHTTPリクエストが果たす機能について説明した。今回はHTTPにおいてリクエストの受け手であり、返してであるHTTPレスポンスの役割についてまとめていく。
HTTPレスポンスの構成
通信の開始は常にクライアント側であり、クライアントが投げるリクエストに対してサーバーは何かしらのリアクションを返す、というHTTPの基本原則は前回のエントリで触れた。HTTPレスポンスとは、受け取ったリクエストに応じてサーバー側からクライアント側に送られる情報である。
HTTPレスポンスは、以下の情報群によって構成されている。
- レスポンスステータス行
- メッセージヘッダ
- データ本体(メッセージボディ)
状態を表すコードが第1行目に登場し、その後詳細な情報を表すヘッダ部が続き、最後にメッセージボディが送られる。この構造はクライアント側から送られるHTTPリクエストと殆ど同一のものであることがわかる。実際に前回HTTPリクエストを確認した2chにアクセスしたときに送られてきたレスポンスを調べてみる。
HTTP/1.1 200 OK Date: Thu, 30 Aug 2012 13:59:10 GMT Server: Apache/2.2.15 Last-Modified: Wed, 02 Jun 2004 15:33:37 GMT Etag: "e8280b-1b63-3dbe269f6b640" Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 2174 Connection: close Content-Type: text/html
これらの情報が私たちのブラウザに送られた後に、メッセージボディ(つまりは2chのhtmlデータや画像)が送られてくるというわけだ。そのデータをブラウザが構築することでこのページが表示されている、というわけ。
レスポンスステータス行
HTTPレスポンスにおいてまず何より大事なのが1行目のステータス行だ。
HTTP/1.1 200 OK
最初の"HTTP/1.1"の部分はWebサーバーがサポートするHTTPのバージョンを表している。次に続く"200"こそがなじみ深いHTTPステータスコードだ。これは要するにアクセスするクライアント側への結果発表みたいなもので、ブラウザからのリクエストをサーバーがどう処理したかを番号で表している。考えてみれば当然で、ホスト側に伝える大量の情報群の中でも、最初に伝えるべきなのは結果なのだ。その辺の書類と同じである。最後の「OK」の部分は、ステータス・コードの補足説明。ここでは無事に要求通りのものをサーバーが持ってきたことを示している。
さて、404や403など、誰でも知っているようなステータスコードもあるだろうが、他にはどのようなものがあるだろうか。先日素晴らしいコンテンツがインターネットで話題になっていたのでそちらを紹介し、ここでは主要なものに留めることにしておく。ぜひ目を通しておきたい。
- 1xx Informational リクエストはサーバーに届けられ、処理は継続する。
- 2xx Success リクエストはサーバーに受理される。200:要望通りのモノをもってきた。成功。おっけー。
- 3xx Redirection リクエストを完了させるために、さらなる処理が必要。
- 301:恒久的な移動。Locationヘッダに移動先は記述される。「このホームページは引越ししました。10秒後に・・・」
- 4xx Client Error クライアント側のリクエストに誤りがあった。お前何言ってるかわかんねーよ。
- 403:Forbidden。リソースにアクセスすることを禁止されている。サーバー側から排他的な処理がなされている場合が多い。アク禁。
- 404:Not Fouund。そんなものなかった。
- 5xx Server Error サーバー側がリクエストの処理に失敗した。
- 500:Internal Server Error。サーバー内部にエラーがあった。プログラムの文法ミスなどで処理が止まるなど。
- 502:Bad Gateway。ゲートウェイ・プロキシサーバーが不正なリクエストを受け取り、これを拒否した。
レスポンスヘッダ部分
リクエストのヘッダフィールドと同じく、レスポンスヘッダフィールドも
フィールド名: 内容
という形式で表される。今回サーバーから受け取った情報を順に見ていく。
Date: Thu, 30 Aug 2012 13:59:10 GMT //メッセージの作成日時を示す Server: Apache/2.2.15 //サーバのベンダー名、バージョン番号を示す Last-Modified: Wed, 02 Jun 2004 15:33:37 GMT //オブジェクトが最後に変更された日時を示す Etag: "e8280b-1b63-3dbe269f6b640" //オブジェクトのエンティティタグ値を示す。ネットワークの帯域を節約するための キャッシュの管理で用いられる。 Accept-Ranges: bytes //オブジェクトの一部に対するリクエストをサーバが受け入れ可能か示す Vary: Accept-Encoding //サーバがレスポンス内容を決定する際にリクエストURI以外に用いたヘッダのリストを示す Content-Encoding: gzip //オブジェクトのエンコーディングを示す Content-Length: 2174 // オブジェクトのサイズをバイト単位で示す Connection: close //中間システムが転送すべきでないヘッダのリストを示す Content-Type: text/html //オブジェクトのタイプを示す
その他のヘッダで重要なものとしては、set-CookieやLocationが挙げられる。
- set-Cookie
クッキーは、まずサーバがSet-Cookieというヘッダを発行する所から始まる。これをクライアントは受け取り、次回以降のアクセスでsetされたCookieをリクエストヘッダに付加してサーバーに送ることでサーバーは一意のクライアントを判別することができ、ショッピングカートや視聴履歴といったシステムが可能となる。サーバがクライアントにクッキーを送る時のレスポンスヘッダは以下のような形式となる。
Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
set-Cookieヘッダを利用してsessionIDをクライアントに送ることでユーザーを同定しているのだから、これさえ入手すれば第三者ユーザーになりすますことも当然可能である。好きな女の子のCookie情報をこっそり引っ張ってこれれば、などと考えてしまう人が時折登場するのも性である。ブラウザが持つCookieとはそれほどに尊いものなのだ。
- Location
これはステータスコード3xx系でよく用いられる。Locationヘッダフィールドは、リクエストの完了や新しいリソースの識別をするため用いられる。受信者をRequest-URI以外の場所にリダイレクトするってこと。3xxレスポンスの場合、Locationはリソースへ自動でリダイレクションさせるためにサーバが望むURIを示すべき。単一の絶対 URI から成る。
Location: http://www.w3.org/pub/WWW/People.html
まとめ
HTTPレスポンスはレスポンス行、ヘッダフィールド、メッセージボディの3つに大別され、レスポンス行では応答のサマリーとして状態を示すステータスコードが記載され、以降のヘッダフィールドにはクライアント側に返すのに必要な形式やサイズといったメタ情報が記されていることが分かった。それらの情報の後にクライアント側が要求するオブジェクト、すなわちhtmlやcssといったコードや画像や音声といったバイナリデータが本体として送信されている。前エントリで学んだリクエストヘッダを受けたサーバーがこのような処理を行うことで、HTTP通信が行われる。主要なステータスコードやヘッダフィールドはちゃんと覚えておきましょう。全2回に分けるほどHTTPで学ぶべき領域は膨大であった。「未だHTTPの5%も理解できていないのでは」とも思うが、今回は一応これで区切りとしておく。
なにか間違いがあったらご指摘ください!
HTTPってなんなの 1/2
※全2回です
HTTPってなんのことだか分かりますか!
ぼくは分かりません!
でもインターネットだいすきです!
このような人は多いと思う(自分含めて)
さっそく学んでいく。
HTTPとはHyperText Transfer Protocol(ハイパーテキスト・トランスファー・プロトコル)の略称である。WebブラウザとWebサーバの間でHTMLなどのコンテンツの送受信に用いられる通信プロトコルのことで、ITIFによりRFC2616で規定されている。ハイパーテキスト転送プロトコルとも呼ばれる。乱暴な言い方をすれば、僕らがブラウザを通じてやってることはだいたいHTTPという規格の上で通信している、ということ。通信プロトコルについてまでまとめると大変なことになるので、また時間のあるときに。とはいえwikipediaに載っている程度の情報はさらっと目を通しておいた方がよい。
http://ja.wikipedia.org/wiki/%E9%80%9A%E4%BF%A1%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB
もうちょい概要
ティム・バーナーズ・リーらが1990年に世界初のWebサーバーとWebブラウザを開発した。サーバーとブラウザ間による通信を行うために彼らが設計した通信プロトコルこそが、HTTPであり、トランスポートプロトコルとしてTCPを使用している。HTTPは名前の通りHTMLやXMLの転送を主な目的としているが、周知の通り音声や映像などのバイナリ形式も転送可能である。リクエスト-レスポンス型のプロトコルであり、クライアント(ブラウザ側)がサーバにリクエストメッセージを送信する。サーバはこれにレスポンスメッセージを返し、基本的にこの時点で初期状態に戻る。つまりこれは、サーバ側がクライアントの状態を保存しないことを意味する(これを解決するCookieについては後述)。他には、ポート番号80をデフォルトで使用すること、TLSによって暗号化されることでセキュリティを保った通信はHTTPSと呼ばれることなどが挙げられる。
HTTPリクエスト
先に述べたように、リクエストを投げるのは常にクライアント側である。逆を返せば、サーバーはリクエストがなければ応答しない。HTTP通信を開始できるのはクライアント側のみなのだ。基本的な考え方は非常に単純で、リクエストは「何を」「どうして」欲しいのかをサーバーに伝える。URLが「何を」、メソッドが「どうして」に当たる。
HTTPリクエストの構成
基礎を確認するのだから静的なウェブサイトが好ましい。試しにhttp://www.2ch.netにアクセスしたときに自分のブラウザから投げたリクエストを確認してみた。firebug(chromeの場合は付属の開発者ツール)なんかですぐに調べられる。
GET / HTTP/1.1 Host: www.2ch.net User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ja,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Referer: http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CE4QFjAA&url=http%3A%2F%2Fwww.2ch.net%2F&ei=pZYzUPf9POrwmAWUoYHACw&usg=AFQjCNFc01jYm6KymcLkeIbDliJNSoyYog&sig2=hRwJ1GN7Jx_gudPqtBVQMw If-Modified-Since: Mon, 09 Jul 2012 16:28:11 GMT If-None-Match: "159100-10b9-4c468198a9cc0"-gzip Cache-Control: max-age=0
HTTPリクエストには
- HTTPリクエスト行
- HTTPヘッダ
- データ本体(メッセージボディ)
の3つのパートが存在する。HTTPリクエストの1行目が、リクエスト内容を示すHTTPリクエスト行(リクエストライン)で、ここには「メソッド」「URI」「HTTPのバージョン」の3つの情報が含まれている。記述方法は以下。URIに関しては後述。
[メソッド][空白][URI][空白][HTTP バージョン] 今回のリクエストではこの部分(ドメインは省略されている、というかサーバー側の絶対パスなのでスラッシュのみ。もちろん階層を下がればindex.htmlなどといった文字列が出現する) GET / HTTP/1.1
今回のようにGETメソッドの場合、HTTPリクエストではデータ本体は送られない。メソッドがPOSTの場合は、HTTPヘッダの後にデータ本体が続く。HTTPヘッダに関してだが、GETメソッドを用いているこのリクエストでは2行目以降はすべてHTTPヘッダである。POSTなど他のメソッドだった場合は次行からメッセージボディが続くことになる。
GET, POSTを初めとするHTTPメソッド
GETやPOSTといったメソッドは私達に馴染み深いが、実は他にもHTTPメソッドは存在する。おさらいも兼ねて以下にまとめる。
- GET
- POST
- GETとは反対にクライアントがサーバにデータを送信する。Webフォームや掲示板の投稿などをイメージすると分かりやすい。GETの場合と同じく、サーバはクライアントにデータを返すことができるが、クライアント側から見ればGETは受け取るメソッドであり、POSTは送信するメソッドなので混同しないようにする。
あとはあまり馴染みのないメソッドたちだが、いつか出会うこともあるだろう。
- PUT
- DELETE
- 指定したURIのリソースを削除する。
- OPTION
- サーバを調査する。例えば、サーバがサポートしているHTTPバージョンなどを知ることができる。
- HEAD
- GETと似ているが、サーバはHTTPヘッダのみ返す。クライアントはWebページを取得せずともそのWebページが存在するかどうかを知ることができる。例えばWebページのリンク先が生きているか、データを全て取得することなく検証することができる。
- TRACE
- CONNECT
- 暗号化したメッセージをプロキシで転送する際に用いる。
URIとは
先に触れたURIについて。URLと名前も概念もなんだか混同してしまいそうだが、一応別の識別子である。が、ことHTTPにおいては殆ど同義といえる。めんどいから概要はWikipediaから。
Uniform Resource Identifier(ユニフォーム リソース アイデンティファイア、URI)または統一資源識別子(とういつしげんしきべつし)は、一定の書式によってリソース(資源)を指し示す識別子。1998年8月にRFC2396として規定され、2005年1月にRFC3986として改定された。URI はUniform Resource Locator (URL) の考え方を拡張したものである。
URIはhttp/httpsやftpなどのスキームで始まり、コロン(:)による区切りのあとにスキームごとに定義された書式によってリソースを示す。また、URIによって示されるリソースはコンピュータが扱うデータに限らず、人や会社、書籍などを示すことも可能である。
(アイデンティファイアとか名前かっこいいな・・・)
要は膨大なウェブの中で、「hogehoge区にお住まいのfoobarさんちのfugafugaさん」みたいに一意の存在を識別するための仕組みであると考えられる。もう少し詳しく見ていこう。
http://www.2ch.net:80/foo?bar#bazというURIについて考える。この文字列は
- http
- www.2ch.net
- 80
- foo
- bar
- baz
に分けられるが、それぞれどんな解釈がされるのだろうか。以下に見ていく。
- scheme
- 最初の文字列はデータリソースにアクセスするための手法を識別する。ここでのスキームは当然http。
- host
- port
- abs-pass
- absolute pass、すなわち絶対パス。そのコンピューター内でのリソースの場所を指定する。スラッシュ(/) をディレクトリ区分に用いる。
- query
- クエリ文字列、よくクエリパラメータとか呼ぶ。絶対パスとの区切りには?を利用する。指定したリソースに情報を流す場合に用いるのだが、GETメソッドを利用する場合にも使われる。
- fragment
がどう使われるか。どの部分がクライアントで解釈されるか、どの部分がサーバーで解釈されるか。
HTTPヘッダ
2ch.netにアクセスしたときのリクエストにも、hostやrefererなどといった文字列があった。これらがHTTPヘッダである。クライアントとサーバーは、HTTPヘッダを使ってデータやソフトウェアの情報をやりとりしている。HTTP/0.9では、データの取得のみを目的としていたので、HTTPヘッダというものは存在しなかったが、wwwが活用され始めるにつれリソースサイズや更新時刻といった「取得するリソースに関連する情報」や、ユーザエージェントの種類やそれを参照するリソースのURIなどの「クライアント側の情報」をやりとりする必要性に迫られ、実際のリソースとは別のメタ情報を扱うものとして、HTTPヘッダが開発されたという経緯がある。ヘッダの書式は、
フィールド名: 内容
という形式で記述される。代表的なリクエストヘッダを列挙する。
- Accept
- サーバのレスポンスに含まれるメッセージボディで受け入れることが出来るコンテンツタイプと各コンテンツタイプの相対的な優先度を指定するリクエストヘッダ。
- Accept-Charset
- レスポンスで返されるメッセージボディの文字コードを指定するリクエストヘッダ。Acceptと同じく複数指定でき品質係数も設定できる。定義済み文字セットはIANAが管理している。
- Accept-Encoding
- クライアントが受信できるメッセージボディのエンコーディングを指定する。
- Accept-Language
- レスポンスの言語(人間の言語)に対する優先度を指定する。言語コードはISO-639の2文字の省略コードを用いる。書き方は他のAccept-群と変わらず。
- Host
- Hostヘッダはhttp/1.1における唯一の必須ヘッダである。必須の理由として、ネームベースのバーチャルホストが用いられた際の名前解決に必要となることが挙げられる。バーチャルホストでは、たとえば192.168.0.100というIPアドレスを持つ1台のホストサーバがあったとして、これにhost1.2ch.net,host2.2ch.net, host3.2ch.netという3つのドメインを割り当てたとする。これによって、クライアントから見るとまるで3台のホストサーバがあるように見えるので、IPアドレスを“節約”することができるのだ。この時にhttp://host3.2ch.net/hogeへリクエストをするとどうなるだろうか。クライアントがリソースを取得するためには、まずホスト名をIPアドレスに変換する、すなわち名前解決をしてサーバを探し出した後にリクエストをする必要がある。(参考:DNSの仕組みについて http://d.hatena.ne.jp/arerreee/20120814/1344960272)だがこの場合リクエスト先のIPアドレスには3つのホストが同居しているので、このままでは望むリソースを取得することができない。対策として、それぞれにIPアドレスを付与する方法もあるがIPv4の資源を無駄にすることになる。そこで、Hostヘッダを使用し予めホスト名をメタデータに明示しておくことで名前解決を行なっている、というわけだ。
Host: www.2ch.net
- User-Agent
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1
- Referer
- どのページから発生したリクエストなのかを示す。つまり、ページAに記されたリンクをクリックしてページBに行った場合に、ページBへのHTTPリクエストにリファラとしてページAが入ってくる。同様に、ページCを表示する際にページ内で使われている画像をリクエストする際に、画像のHTTPリクエストにリファラーとしてページCが入る。リファラの活用はクロスサイトリクエストフォージェリ(いわゆるCSRF)対策としても一般的であろ、統計的用途にもよく使われる。余談だが、本来の参照元という意味の英単語は"referrer"であるにもかかわらず、HTTPリファラの場合は意図的に"referer"と綴る。これは、HTTPが策定された時にヘッダ名を間違ったスペルで書いてしまい、それが今でも使われているという歴史的経緯のためである。仕様上のヘッダ名は"referer"であるため、特にHTTPヘッダを直接扱うようなソフトウェアプログラムの場合、"referrer"と綴ると意図通りに動作しない場合すらある。ここではgoogleから辿ってきたので次のような内容となる。
Referer: http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CE4QFjAA&url=http%3A%2F%2Fwww.2ch.net%2F&ei=pZYzUPf9POrwmAWUoYHACw&usg=AFQjCNFc01jYm6KymcLkeIbDliJNSoyYog&sig2=hRwJ1GN7Jx_gudPqtBVQMw
- Cookie
- Content-Disposition
次回に向けて
HTTPについてまとめるとプロトコルやポートなどといったTCP/IPの領域、さらにはリクエストラインのメソッドやリクエストヘッダなどのおびただしい形式などが出現して頭が破裂するかと思った。特にリクエストヘッダにはヘッダごとに更に属性を保持していたりでやっかい。少しずつ覚えて記事にしていこうと思う。やっぱ本1冊程度は読んでおくべきだよなーこの辺、などと。
次回は残りのHTTPレスポンスについて書く。
何か間違いがあったらご指摘ください。
githubのセットアップ
備忘録です。
MacOS or Linuxならこれで大丈夫かと。githubにアカウント作成済み、gitは既に入れてあるものする。確か自分の環境では、Macならhomebrew経由でインストールするか、バイナリで配布されているものを使えばよい。Ubuntuなら「sudo apt-get install git」でおk。
SSH公開鍵をさくっと作る
githubとの通信にはSSHが必要になる。まずは公開鍵と秘密鍵のペアを作っておく。さっさと作ってしまおう。カレントディレクトリは自分のホームディレクトリで。
cd .ssh もし.sshディレクトリが存在しなければ mkdir .ssh <-.sshディレクトリに移動 ssh-keygen -t rsa -C "githubに登録したアドレス" <-公開鍵作成
ssh-keygenすると「どこに鍵作る?」などと聞いてくるが、.ssh内でよいので空のままEnterで。続けてパスワードが求められるので適当なパスワードを設定しておく。確認でもう一度タイプ。
--[ RSA 2048]---- | .=.E | | = | | + . | | o + o | | o O S | | o + = o | | + + o . | | o * . | | o . | +-----------------+
こんなんが出たら公開・秘密鍵のペアが作成されているはず。lsでid_rsa(秘密鍵)とid_rsa.pub(公開鍵)が出来ているのを確認する。
githubへ公開鍵の登録をする
githubにアクセスし、AccountSettingsからSSHKeysの項目を開き、新しく鍵を登録する。鍵は先ほど作った公開鍵のid_rsa.pubを使う。
cat id_rsa.pub
これで出力された文字列をコピーして、github側に貼り付ける。名前は適当に入れておく。保存すれば公開鍵の登録は終了。
試しにSSHでgithubに接続してみる
以下のコマンドを打つ。
ssh -T git@github.com
接続を許可するかどうか聞いてくるはず。そしたらyesと打ち込んであげればよい。あと恐らくクライアント側からパスワードが要求されると思う。「hogehogeさんこんにちは!とはいえまだ設定終わってないぜ!」みたいなこと言い出したら接続に成功している。ついでにgithubにpushしたときに使われる名前なども登録してしまう。
git config --global user.email "hogehoge" git config --global user.email "foo@bar.com"
リポジトリ作成とgit push
さて通信もできたところで、ささっとリポジトリ作成からpushするところまでやってしまいましょう。
ブラウザからgithubに行き、ダッシュボードかどこかで新規リポジトリ作成をクリック。TestRepoという名前にでもしておきましょうか。画面通りに進んで名前だけ決めておけばあと別になにもしなくてもよい。
で、github側の登録が済んだら、再び端末。ローカルリポジトリを作りましょう。カレントはどこでもいいので、リポジトリを置きたい場所でブラウザで作ったリポジトリと同名のディレクトリを作成する。
mkdir TestRepo cd TestRepo git init TestRepo touch UNKO echo TestRepo is my first contact by git. > UNKO
git initは文字通り初期化、リポジトリの作成コマンドである。gitリポジトリの管理ファイルなどがこのコマンドを打った後作成されているはずである。なんでもいいのでとりあえずファイルを作るためにtouchしている。一応UNKOファイルに文字を入れておく。ファイルが無事できたが、それをローカルリポジトリに登録していないので登録しておく。コミットもここでしておかなければならない。サーバー側のリポジトリ(github側)にpushするときにエラーが出る。
git add UNKO git commit -m 'unko!!!'
無事ファイルがローカルリポジトリにadd,commitできたら、サーバー側に上げてやる。初めてpushする前に、まずはリモートリポジトリがどこにあるのか設定する一文を書いてやらなきゃならない。
git remote add origin git@github.com:"ゆーざー名"/"リポジトリ名(ここではMyRepo)".git git push -u origin master
これで怒られずにpush完了のお知らせが来ていることを待つ。githubにアクセスして、期待通りTestRepoにUNKOファイルがあれば無事セットアップ完了。お疲れさまでした。
あとの流れ
ローカルリポジトリとリモートリポジトリが無事繋がったので、あとはやりたい放題。リポジトリ管理に入れたいファイルやディレクトリをTestRepoに入れるなり、また新しくリポジトリを作成したりなど。既存のリポジトリに追加する場合、基本的には以下のコマンドでおk。
git add hoge git commit -m 'massage' git push -u origin master
githubからリポジトリをコピーするコマンドをよく忘れるのでこれも追記。
git clone git://github.com/xxxx/xxxx/xxxx.git