銀色うつ時間

思い出すたび何か胸につっかえてるだけ

PCを新調しました

もはや1年以上「PCがほしい、PCがほしい」とツイートし続けてきたが、今回ついに新しいPCを新調する運びとなった。今までMacBook(late 2006)という化石のようなPCで戦ってきたわけだけれど、開発者の端くれとしていつまでも貧弱なハードウェア構成のマシンを使うわけにはいかない(白目 加えて、学生時代と異なりPCを外に持っていく機会もほとんどないので、大きなディスプレイに見合ったパワフルなデスクトップPCを1から構築することにした。私が出す要件は以下の通りである。

基本方針

高性能なモデルがほしい
  • CPU
    • 私のMacBookは、一時代を築いたintel Core 2 duoだった。当時はあまりの速さに感動していたが(その前はamdの廉価モデルの何かを使っていた記憶)、時代の進歩とは残酷なもので、Sandy世代のCPUを搭載した職場のMacBookProを常用するようになってからは不満が募るようになってしまった。どうせ買い換えるのならばIvy世代の最新CPUにしようと思う。
  • メモリ
    • 私のMacBookは、6年の歳月をかけて少しずつカスタマイズされいった。当然メモリも最大までカスタマイズしてあったわけだが、それでも限界は3GBである。現在のモダンブラウザやIDEを同時に立ち上げたら最後、「空きメモリ容量:ほげMB」などという苦しみを味わうしかなかった。今回はふんだんにメモリを搭載したい。
  • グラフィクス
    • 私のMacBookは、Intel GMA95というグラフィクスプロセッサであった。これはメインメモリと共有型のもので、64MB DDR2 SDRAMメモリ搭載とある。フルHDの外部ディスプレイを利用していたのだが、たびたび画面にちらつきがあったり、スクロールがカクつく現象が起きていた。貧弱なリソースを更に切迫していわけだ。私自身オンラインゲームを利用することはないが、フルHDのディスプレイ2枚程度は問題なく処理できるGPUがほしい。
  • ストレージ
    • 私のMacBookは、6年の歳月をかけて少しずつカスタマイズされていった。ストレージも例外ではなく、過去2度ものデータ損失事故を引き起こしている(1度は100GB近い音楽データを失った)。現在は当然SSD化もされており、更に光学ドライブの場所に500GBのHDDをマウントしている。とはいえ現在は保有するデータも少ないので、SSDとバックアップ用のHDDさえ用意されていればよいと判断した。
極端な大型化を避ける
  • 「なんなんだ、これは...」
    • 先日まで、自作PCを組むべきか、MacMiniの上位モデルを買うべきか悩んでいた程度には小型のマシンがほしいと考えていた(しかも新型のMacMiniなら2.6GHzのクアッドcore-i7が78000円とMacにしてはそれほど高くない)。多少の大きさは構わないのだが、秋葉原電気街諸店舗における自作PCのケースコーナーに溢れているような、独特のカルチャーをもった、厨二病というか、「これが俺のマシンや!どやぁ!(LEDで光を帯びたファン「ファンファン」)」みたいなセンスには我慢ならなかったし、何よりあの灯油ケースみたいなサイズが許せない。僕の家は狭いし、ものが多い。自作するのなら、大きさはそこそこに、値段は多少かかってもいいので圧倒的にハイセンスなケースを探すべきだと判断した。
FYI : http://blog-imgs-46.fc2.com/m/o/t/motobuyer45/cosmos22.jpg
  • 拡張性や排熱
    • とはいえ、mini-ATXのような小型マザーに高性能CPUを載せ、かつケースも小さくとなると、電力供給や排熱の問題がボトルネックになることは確定的に明らかだ。また、拡張性に関しても不安が残る。そこでマザーボードはmini-ATXではなくmicro-ATXとし、micro-ATX規格が搭載可能という条件で比較的小型の、私の眼鏡に叶うセンスを有したケースを探すこととした。
予算はできれば10万以下
  • 悪くないスペックのMacMiniが8万(カスタマイズ入れて10万)で買えるのにわざわざ自作するとなったら、それを超えるスペックで10万以下に抑えたい。とはいえ、今回はコンピュータの勉強的側面もあったのでそこまで気にしない。

ハードウェア構成

お待ちかね、今回このようなわがままな要望を満たす運びとなったハードウェア構成が以下のとおりだ。費用も合わせて明記しておく

  • CPU : i7 3770k
  • GPU : nvidia GEFORCE GT640
  • RAM : 32GB
    • Patriot Memory DDR3 PC3-12800 8GB × 4 \9,940
  • Storage : SSD240GB + HDD300GB
    • Intel SSD 335SEROES 24GB \14,780
    • HDDは自宅で使っていないものをマウント
  • OS : windows8 + fuckOSX
    • windows 8(dsp) home premium \10,800
    • fuckintoshな夢は次のエントリで解説する
  • Motherboard : GIGABYTE micro-ATX
  • PowerSupplyUnit : 玄人志向
    • KRPW-P2-650W/85+ \6,480
  • ODD
  • Case
    • abee AS Enclosure ASE-LP210 \19,980
  • Trackpad
    • Apple MagicTrackpad \6,800
  • その他

f:id:arerreee:20121110172436j:image:w360

合計して11~12万程度になるかと思う。ケースが2番目に高い買い物になっている。無駄にケースにお金をかけているし、windowsOSやtrackpadまで購入しているので少し足がでてしまったが、全く問題ない。

ちなみに、これが今まで使ってきたMacBookの技術仕様だ。
http://support.apple.com/kb/SP23?viewlocale=ja_JP&locale=ja_JP

知人の世話になりつつ、実際に組んでみる。マシンとして組む過程や、何度もBIOSを確かめることでコンピュータがどのように動いているのか少なからず理解できたように思う。問題なく起動することができたが、今回windows8はHDDにインストールした。HDDだから多少の遅さがあるとはいえ、動作している。今のところ、音や熱が問題になっている感覚はない。非常に静かで、安定した様子を見せている。

出来上がり

ケース

これが私の探し求めていた、自作PC界隈の文化とは一線を画すセンスフルなケース。黒やシルバーの先行く、ゴールド。金は上質の象徴だ。ケースから黄金の金が鳴っているのが写真で伝えられないのが遺憾である。

f:id:arerreee:20121110170254j:image:w360

全容。完成されたボックスの造形である。これがほんとの、黄金比や!

f:id:arerreee:20121111234437j:image:w360

オーディオ機器としての存在感もばっちりである。これを使うユーザーはまったく新しいGoldExperienceに打ちのめされること請け合いだ。

音・映像
  • オーディオ機器に関しては、ソニーの標準サイズのコンポを出力として利用している。音質に関しては既に10年以上前からあるものなのでなんともいえないが、そのあたりの数千円程度のPCステレオよりはよいと思われる。
  • 映像に関しては、DELLの23インチフルHDをそのまま利用している。補助ディスプレイとして、32インチの東芝REGZAHDMIで繋いでいる。以外と問題なく表示できており、GPUのお陰か動画も美しく描画されるので満足である。
スコア

さて、今回組んだPCがどれ程のパフォーマンスを持つのか、試しにテストしてみようと思う。Geekbench2というアプリケーションを用いて測定してみた。測定結果は以下の通りだが、これは32bit版として測っているので、実際にはもっとスコアが高く出るような気もする。

f:id:arerreee:20121111233009p:image:w360

ちなみに往年のMacBookのスコアはこちら

f:id:arerreee:20121112002742p:image:w360

新しいPCが64bitであることを加味すると、ほとんど5倍かそれ以上の速度にはなっているようです。メモリが32GBある安心感が素晴らしい。動画を見ながらIDEどころか、動画を見ながら動画が見れるのではないでしょうか!これでHuluドリブンな開発ができますね!(白

f:id:arerreee:20121112002503j:image:w360

まとめ

  • ぱそこん組むって楽しいですね
    • 積極的に厨二病になろう!
    • 黄金のケースこそ至高
  • OSまわりの設定は次エントリ
  • 時代の進歩とは
    • 6年間使った黒いMacBookには愛着がある

”To be C or not to be C. That is the question.”

半年くらい経ったのでそこそこにまとめる

身につけたこと/今後の展望

身につけたこと、とはいえどれも中途半端だし、自信を持って「できます」といえるレベルは程遠い。上限が見えないからこそ面白くはあるんだけど、みんなどこまでやって「できます」って言えるようになるんだろう...

  • UNIX/Linux基本的な操作
    • 簡単なシェルスクリプトくらいなら
    • コンピュータに対する理解が甘いので、もっといじる
  • Webアプリケーションへの理解
    • HTTPとか、TCP/IPとか
      • request/responseモデルの基本的な通信は学んだ
      • サーバー間通信の問題などつい最近まで知らなかったので、今後もヒマな時に本を読んだりして補いたい
      • WebSocketあたりはほとんど触れてない
    • セキュリティ
      • XSSCSRFなど対策すべき攻撃手法の基本は学んだ
      • とはいえワンタイムトークンの実装など曖昧な認識がある
    • CMSの利用
      • 個人でwordpressを利用したサイトを構築した
      • 使い方のイメージはつかめたけど、プログラミングじゃない感が激しいのであまりモチベーションがない
      • nginxもとりあえず導入してみただけで、まだ仕様についてちゃんと理解できていない
  • テスト
    • あまり学べていない
    • JavaでSelenium2を使った自動テストをやった程度
  • HTML/CSS
    • 卒なく組めるようにはなった
    • classやname,idの付け方が下手くそ
    • CSSの修正にめちゃくちゃ時間がかかる
    • floatやalign属性への理解不足
  • PHP/template engine
    • まあまあ書けるようにはなった
    • オブジェクト指向関連の処理系についてまだ良くわかっていない点が多いので、1つずつ潰していく
  • javascript
    • フリーダム言語なのでとりあえず動くようにはできるけど、まだ全然言語仕様についての理解が足りない
    • 言語仕様だけでなく、DOM操作、ライブラリについても学ぶ必要がある
    • これらを切り分けて理解していくのが大事
  • Database
    • MySQLだけ。一応クエリ最適化なども経験した
    • 今はフレームワークがほとんど吸収してくれているので自分でSQL文を投げることもない
    • 自分で設計する機会もほとんどないので、これはプライベートで理解を深めるしかない
    • MongoDBとかどうなんでしょう

超ざっくりかつカテゴライズ適当過ぎるけど、こんなものだろうか。んで、次。

今後身につけたいこと

今まで学んできたことの理解を更に深めることに加え、いわゆるスクリプト言語とは別のものをちゃんと学んでおきたいな、と思っている。なぜなら実際にプログラムを実行するコンピュータについてや、プログラムが動く仕組みなどへの理解が足りていないからだ。限られたリソースの中で厳格なコードによって処理が行われる一連の動作、ミニマルな形で学ぶことができる低級言語がいいと思っている(これとは別だが、関数型言語も学びたい)。あと、普段使っているフレームワークの内部実装などを積極的に調べて、コードをちゃんと読む機会を増やしたい。というわけで、今は「新しいサービスを世の中に出したい!」みたいな意識が全然なくて、こんなに意識が低くてよいものかと若干不安ではある。

  • 今までの理解を更に深める
    • コンピュータ・ネットワーク・セキュリティ全般
      • 「なぜ動くのか」シリーズを片っ端から読むといいかもしれない
    • 「効率的なWebアプリ~」とかっていう本とか
    • UNIX/Linux
    • PHP/HTML/CSS/javascript
      • 今後も経験積んでいきましょう
      • 公式ドキュメントに目を通すようにしましょう
      • パーフェクトjavascript読みましょう
  • 新しく勉強したいこと
    • なにか言語1つ
    • 低級言語
      • 型宣言やメモリ管理、ポインタなど厳格なプログラミング
      • アルゴリズムやデータ構造などが学べるもの
      • 候補1 C言語
        • Cを学んでおいて今後の人生で役に立たないことはないと思う
        • Cを使って独自のプログラミング言語を作ってみるのはいい経験になるかもしれない
      • 候補2 C++
      • C++であれば低級言語を学びたいという要件を満たしつつ、オブジェクト指向についても学べる、実践で使う機会もある
        • 一石三鳥
    • 関数型言語
      • ある程度実践的でありつつも、全く別の概念を持ったプログラミング言語を学んでみたいという欲求
      • 候補3 Scala
        • 関数型でありながら、殆ど無いとはいえJavaの知識が活かせる(というかJavaも一緒に学べるのではという期待)
        • 並行性プログラミングなどが楽しそうでありつつ、Android開発もできるのではないかという期待
        • まあ同時に複数の概念が学べるはずもない
  • コードを読む機会を増やす
    • 今使っているフレームワーク
      • 職場のもの
      • jQueryの内部実装をがんばって読んでみる
    • github
      • 気になるコードを舐めるように読む
  • その他
    • 開発環境
      • zsh関連もっと充実させる
      • vim関連もっと充実させる(便利な使い方覚える)
        • vimgrep課題
      • まともに使えるIDEを用意する
      • 家では基本IDE使うようにする
    • バージョン管理
      • とりあえず個人で開発管理しているものは積極的にgitで管理する
    • 記録
      • とりあえずなんでもいいからブログ書け

だらだら羅列したものの、今はこれに尽きる。

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;

実行してみる。

f:id:arerreee:20120914023259p:image

ちゃんとおねえさんの数えた通りの数字になっていますね!

ただ、おねえさんと違って私たちは手近なところにスーパーコンピューターなんてあるはずがないので5x5か6x6が限界だと思います(5マスのときは20秒くらいかかりました)。

さもないと「あれから25万年がたった・・・」なんて話になるので、実行はお気をつけて!


githubに置いときます

https://github.com/sisidovski/CombinationalExplosion

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://www2.2ch.net/

レスポンスステータス行

HTTPレスポンスにおいてまず何より大事なのが1行目のステータス行だ。

HTTP/1.1 200 OK

最初の"HTTP/1.1"の部分はWebサーバーがサポートするHTTPのバージョンを表している。次に続く"200"こそがなじみ深いHTTPステータスコードだ。これは要するにアクセスするクライアント側への結果発表みたいなもので、ブラウザからのリクエストをサーバーがどう処理したかを番号で表している。考えてみれば当然で、ホスト側に伝える大量の情報群の中でも、最初に伝えるべきなのは結果なのだ。その辺の書類と同じである。最後の「OK」の部分は、ステータス・コードの補足説明。ここでは無事に要求通りのものをサーバーが持ってきたことを示している。

さて、404や403など、誰でも知っているようなステータスコードもあるだろうが、他にはどのようなものがあるだろうか。先日素晴らしいコンテンツがインターネットで話題になっていたのでそちらを紹介し、ここでは主要なものに留めることにしておく。ぜひ目を通しておきたい。

先輩と覚える HTTP ステータスコード ― Gist - Gist - GitHub

https://gist.github.com/3401612

  • 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: 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に載っている程度の情報はさらっと目を通しておいた方がよい。

通信プロトコル - 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
    • 指定されたURIのリソースをサーバーから取り出すHTTPの最も基本的な動作。
  • POST
    • GETとは反対にクライアントがサーバにデータを送信する。Webフォームや掲示板の投稿などをイメージすると分かりやすい。GETの場合と同じく、サーバはクライアントにデータを返すことができるが、クライアント側から見ればGETは受け取るメソッドであり、POSTは送信するメソッドなので混同しないようにする。

あとはあまり馴染みのないメソッドたちだが、いつか出会うこともあるだろう。

  • PUT
    • 指定したURIにリソースを保存する。URIが指し示すリソースが存在しない場合は、サーバはそのURIにリソースを作成する。画像のアップロードなどが代表的。
  • DELETE
    • 指定したURIのリソースを削除する。
  • OPTION
    • サーバを調査する。例えば、サーバがサポートしているHTTPバージョンなどを知ることができる。
  • HEAD
    • GETと似ているが、サーバはHTTPヘッダのみ返す。クライアントはWebページを取得せずともそのWebページが存在するかどうかを知ることができる。例えばWebページのリンク先が生きているか、データを全て取得することなく検証することができる。
  • TRACE
    • サーバまでのネットワーク経路をチェックする。サーバは受け取ったメッセージのそれ自体をレスポンスのデータにコピーして応答する。WindowsのTracertやUNIXのTracerouteとよく似た動作。
  • CONNECT
    • 暗号化したメッセージをプロキシで転送する際に用いる。
URIとは

先に触れたURIについて。URLと名前も概念もなんだか混同してしまいそうだが、一応別の識別子である。が、ことHTTPにおいては殆ど同義といえる。めんどいから概要はWikipediaから。

Uniform Resource Identifier(ユニフォーム リソース アイデンティファイア、URI)または統一資源識別子(とういつしげんしきべつし)は、一定の書式によってリソース(資源)を指し示す識別子。1998年8月にRFC2396として規定され、2005年1月にRFC3986として改定された。URI はUniform Resource Locator (URL) の考え方を拡張したものである。

URIはhttp/httpsftpなどのスキームで始まり、コロン(:)による区切りのあとにスキームごとに定義された書式によってリソースを示す。また、URIによって示されるリソースはコンピュータが扱うデータに限らず、人や会社、書籍などを示すことも可能である。

(アイデンティファイアとか名前かっこいいな・・・)

要は膨大なウェブの中で、「hogehoge区にお住まいのfoobarさんちのfugafugaさん」みたいに一意の存在を識別するための仕組みであると考えられる。もう少し詳しく見ていこう。

http://www.2ch.net:80/foo?bar#bazというURIについて考える。この文字列は

  • http
  • www.2ch.net
  • 80
  • foo
  • bar
  • baz

に分けられるが、それぞれどんな解釈がされるのだろうか。以下に見ていく。

  • scheme
    • 最初の文字列はデータリソースにアクセスするための手法を識別する。ここでのスキームは当然http。
  • host
    • 次のwww.2ch.netはホスト名、つまりそのリソースを持っているコンピュータ(たいていはサーバー)の名前を指定する。IPアドレスによる指定も可能だが奨励されていない。
  • port
    • ファイル共有ソフトなんかのお陰で開発に携わらない人間にも馴染みが深いポート番号。これを指定する。先に述べたようにデフォルトのHTTPが扱うポート番号はWell known portとして80番が予約されてるが、それ以外の番号を使用することも可能。8000や8080などをテスト用として利用することや、セキュリティの観点から別の番号を用いることもある。ポート番号が明示されていない時は80を使用する。ポートに限らずTCP/IP関連はまた別の機会に。
  • abs-pass
    • absolute pass、すなわち絶対パス。そのコンピューター内でのリソースの場所を指定する。スラッシュ(/) をディレクトリ区分に用いる。
  • query
    • クエリ文字列、よくクエリパラメータとか呼ぶ。絶対パスとの区切りには?を利用する。指定したリソースに情報を流す場合に用いるのだが、GETメソッドを利用する場合にも使われる。
  • fragment
    • 部分識別子。絶対パスとの区切りには、#を用いる。fragmentもURIの中に含まれるが、"http_URL"の中にはfragmentは含まれない。HTTPにおいて、fragmentはリソース内の特定部分を指すものであり、即ち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
    • ブラウザの種類やOSの情報。アクセスしているのがブラウザではなく検索エンジンのクローラの場合、Googlebotなどの名前が入る。歴史的経緯からどのブラウザもMozillaを入れていたりする。また、モバイル端末やキャリア、OSの識別も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
    • クッキー(Cookie)は実のところRFCによって定義されていいない非標準HTTPヘッダである。元々ユーザエージェント(Webブラウザ)によって保存される「小さな」ファイルを指す。主に「状態管理」のために利用され、ログイン情報やショッピングカートを実現するために利用されている。Cookie、Set-Cookieという専用のHTTPヘッダ。
  • Content-Disposition
    • これも非標準。Content-Dispositionは、本来MIME仕様に従うデータの提示的情(presentational information)を転送するためのヘッダだが、HTTPはメッセージの形式がMIMEに似ているので、HTMLフォームからmultipart dataをアップロードする際にも流用されている。つまりファイルのアップロードに用いられるヘッダ。filename属性を使うと、転送されたデータのファイル名をデータの送信側が示すことができる。

次回に向けて

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側に貼り付ける。名前は適当に入れておく。保存すれば公開鍵の登録は終了。

試しにSSHgithubに接続してみる

以下のコマンドを打つ。

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

DNSの仕組みについて

日頃から私達のネットを支えるDNSについて。IPアドレスに対して対応する適切な名前を返してくれるサーバー、くらいの認識しか持っていなかったのだが、理解を深めるために調べてみました。

そもそもDNSサーバー(ネームサーバー)ってなんだ

Domain Name System(ドメイン ネーム システム、DNS)はインターネットを使った階層的な分散型データベースシステムである。1983年に情報科学研究所 (ISI) のポール・モカペトリスとジョン・ポステルにより開発された。現在では主にインターネット上のホスト名や電子メールに使われるドメイン名と、IPアドレスとの対応づけを管理するために使用されている。 -wikipediaより

これは歴史的経緯から考えるとわかりやすい。TCP/IPのネットワークプロトコル下では、それぞれの ホスト(コンピュータやルータなど)は、IPアドレスによって識別され、通信が行われている。インターネットに接続されるすべてのホスト、すなわちコンピュータは固有のIPアドレスを保有しているのだ。すなはち、どのホストにアクセスする際も最終的にはIPアドレスを知る必要がある。とはいえ、IPアドレスは最大12桁(ipv4では)の十進数だがこれを把握するのは非常に難しいので、IPアドレスを人間でも覚えられるように別の文字列に置き換える機構が生まれた。これがDNSというわけだ。試しにブラウザから以下のIPアドレスを叩いてみよう。

124.83.203.233

ブラウザにはyahoo!japanのトップページが表示されるはずだ(20012/08現在)。このようにIPアドレスに対して対応する文字列(これがURL)を渡す役割をするのがDNSである。ちなみにこの仕組こそが「名前解決」という名前で呼ばれるものだ。余談だが、IPアドレスを調べるためには、hostコマンドを用いる。「host [調べたいドメイン]」と打つだけ。

【追記】

ipv4において最大12桁のアドレスは、8bit * 4 で 32bitとなる。

ドメイン構成について

世の中に存在するIPアドレスは膨大だ。どう考えてもとても1つのコンピューターで処理できる量ではない。そう考えると、DNSサーバー(ネームサーバーとも呼ばれる)も膨大な数が存在するのだろうと想像がつく。では、世界中にあるDNSサーバーはどのようにして役割分担をしているのだろうか。URLはホストとドメインの連結文となっており、ピリオド「.」で区切られていることに着目したい。例えばwww.yahoo.co.jpだと、

jp         ->トップレベルドメイン(国別コード)
|-co.jp       ->第二レベルドメイン(組織種別コード)
|-yahoo.co.jp    ->第三レベルドメイン(組織名)
|-www.yahoo.co.jp  ->第四レベルドメイン
最大255文字

となっていることが分かる。この階層構造において、yahoo.co.jpはco.jpの配下であり、jpの配下という構成で成立している。組織名は、さらに組織内の階層をピリオドで区切って指定できる。例えばwww.dev.yahoo.co.jpなどといった形式である(これをサブドメインという)。

名前解決

それぞれのネームサーバーは担当するドメインの対応表を保有しており、この木構造のノード、つまりはピリオドを辿ることで、最終的なIPアドレスが得られるという仕組みだ。ここで、「木構造の最上位には何が位置しているのか?」という疑問が生じる。我々の期待している通り、最上位には「ルートサーバー」と呼ばれるネームサーバーが全世界に13台分散配置されており、こいつらがDNS界の親玉なわけだ。とまあそんな構造をもったDNSによる名前解決、その処理の流れは以下のように完結にまとまる。

  • まず最寄の(送信元ホストと同じドメインの)ネームサーバーに問い合わせる
    • 目的のアドレスがあれば、ここで解決
  • 最寄のネームサーバーになければ、まずルートサーバーに問い合わせる
  • jpドメインのネームサーバーに問い合わせる
    • このネームサーバーはco.jpドメインを管理するネームサーバーのアドレスを返す
  • co.jpドメインのネームサーバーに問い合わせる
    • このネームサーバーはyahoo.co.jpドメインを管理するネームサーバーのアドレスを返す
  • yahoo.co.jpドメインのネームサーバーに問い合わせる
    • このネームサーバーはwww.yahoo.co.jpドメインを管理するネームサーバーのアドレスを返す
  • www.yahoo.co.jpドメインのネームサーバーに問い合わせる
    • 対応表から124.83.203.233というIPアドレスを割り出し、これをクライアントに返す

hostsとは

DNSと同じように、IPアドレスとホスト名のマッピングを行う原始的な仕組みが、「hosts」ファイルだ。各ホストがローカルファイルとしてマッピング情報を管理している。LinuxMacOSでは「/etc/hosts」に存在するファイルそれに当たる。hostsファイルとは、ローカルでホスト名をIPアドレスに変換する際に参照するファイルだ。このファイルは先に述べた名前解決の流れの中で用いられる。「google.co.jp」というホスト名を、「216.239.33.100」という実際のIPアドレスに変換する時に参照するのだが、ここで重要なポイントは、このhostsファイルの記述はDNSサーバーによる変換より優先されるということだ。/etc/hostsに以下を追加してみる。

216.239.33.100 yahoo.co.jp

hostsファイルはこのように「IPアドレス ホスト名」というように書くのだが、この場合はどうなるだろうか。結果としては、ブラウザからyahooのアドレスを打ち込んだとき、表示されるページはgoogleになる。先に述べた、DNSを参照してyahoo.co.jpのIPである124.83.203.233に辿り着く前にhostsファイルで変換されてしまい、google(216.239.33.100)に飛ばされるわけだ。hostsファイルの設定は大規模な名前解決の手段とはならないものの、特定ページへのアクセスを別の参照先に飛ばしたい場合や、ローカル環境での開発などに有用である。



以上!なにか間違いがあったら指摘ください!