チャンクについて:response.on('data',fn(chunk){}) で
node.jsをやっている初心者ですが、今回はHTTPのチャンクについて自分なりに調べてみました。※チャンクについての理解が間違っていたようです。このエントリーはチャンクについては何も書かれていません。
以下にチャンクド・エンコーディングについて説明する。
HTTP/1.1サーバは、複数の要求に対応したコンテントをひとつの応答に含めて返すことができる。その場合はコンテントごとを固まり (Chunking:厚切りとか、かたまりとかいう意味だが、おだんごとか、もっと下品に馬糞とか?いうイメージ) にしてこれを複数ボディ部に収容する。このようなHTTP応答のヘッダには:Transfer-Encoding: Chunked
なる行を含めるとともに、以下のルールでボディ部を構成する。....
http://www.cresc.co.jp/tech/java/Servlet_Tutorial/Lesson_38.htm
大きなHTMLページをリクエストするとチャンクするんでしょうか?
※チャンクしませんでした。
チャンクしました。最新node.jsの、1ページの巨大なドキュメントをリクエストしたら、約16個のチャンクが僕のさくらVPSにやって来ました。dataイベントが複数回発動したのは事実ですが、header情報に「Transfer-Encoding: Chunked」が含まれていないことからも分かるように、これはチャンクではありません。チャンクだったり、パケットだったりバッファの分断だったりいろいろ可能性があるので、dataという広い言葉を使っているのかも知れません。
ただ、上の引用サイトが言っている「Transfer-Encoding: Chunked」はヘッダ情報(response.headers)には入っていませんでした。なぜ・・・?
各チャンクについて調べる
プログラムを走らせて、チャンクを調べました。調べた事とコードは以下です。
チャンクの総数チャンクのバイト数前のチャンクとのタイムラグ
確認用のコード
このコードは、謝った理解のもと書かれています。中にある「チャンク」は、実際にはチャンクではありません。
/* query3.js 大きなHTMLをリクエストして、以下を調べます。 ・チャンクは何個? ・各チャンクは何バイト? ・チャンク間はどれくらい時間が空くか */ Date.prototype.getDelta = function(){ return parseInt(new Date() - this, 10); }; // ストップウォッチのスプリットみたいな機能(前回から今の間の時間) Date.prototype.lastTime = -1; Date.prototype.getSplitTime = function(){ var d = new Date(); if (this.lastTime<0) { this.lastTime = d; } var s = d - this.lastTime; this.lastTime = d; return parseInt(s, 10); }; // バイト数カウント http://www.openspc2.org/reibun/javascript/string/026/ function getByte(text) { count = 0; for (i = 0; i < text.length; i++) { n = escape(text.charAt(i)); if (n.length < 4) count++; else count += 2; } return count; } var d = new Date(); var http = require('http'); var nodejsorg = http.createClient(80, 'nodejs.org'); // 1. リクエストのタイミング console.log('request! split:' + d.getSplitTime()); var request = nodejsorg.request('GET', '/docs/v0.3.5/api/all.html',{'host': 'nodejs.org'}); request.end(); request.on('response', function (response) { // 2. レスポンスがあったタイミング console.log('on response! split:' + d.getSplitTime()); /* for (var k in response.headers){ console.log('response.headers.' + k + ' ... ' + response.headers[k]); } */ response.setEncoding('utf8'); var chunkNum = 0; response.on('data', function (chunk) { // 3. 各チャンクのタイミング。チャンクのバイト数も見てみる console.log( ['on data! split: ', d.getSplitTime(), ' | bytes: ', getByte(chunk)].join('') ); chunkNum++; }); // 4. 全コンテンツ、ロード終了。 response.on('end', function(){ console.log('on end! split: '+d.getSplitTime() + ' | sum: ' + chunkNum + ' chunks'); }); });
結果
上記のコードを走らせた結果です。5回の結果を載せてみます。※「chunks」とありますが、実際にはchunkではありませんでした。
$ node query3.js request! split:0 on response! split:232 on data! split: 2 | bytes: 4137 on data! split: 112 | bytes: 8688 on data! split: 114 | bytes: 17376 on data! split: 114 | bytes: 7240 on data! split: 3 | bytes: 3312 on data! split: 2 | bytes: 22746 on data! split: 109 | bytes: 15928 on data! split: 13 | bytes: 2280 on data! split: 2 | bytes: 23784 on data! split: 98 | bytes: 4344 on data! split: 3 | bytes: 12832 on data! split: 6 | bytes: 1648 on data! split: 5 | bytes: 27023 on data! split: 99 | bytes: 5792 on data! split: 1 | bytes: 1280 on end! split: 1 | sum: 15 chunks $ node query3.js request! split:0 on response! split:349 on data! split: 3 | bytes: 4137 on data! split: 112 | bytes: 8688 on data! split: 113 | bytes: 2896 on data! split: 2 | bytes: 14480 on data! split: 113 | bytes: 10552 on data! split: 7 | bytes: 21298 on data! split: 32 | bytes: 2896 on data! split: 75 | bytes: 5792 on data! split: 12 | bytes: 10968 on data! split: 4 | bytes: 20888 on data! split: 23 | bytes: 2896 on data! split: 40 | bytes: 2896 on data! split: 33 | bytes: 7240 on data! split: 14 | bytes: 7040 on data! split: 1 | bytes: 22879 on data! split: 26 | bytes: 5792 on data! split: 1 | bytes: 2896 on data! split: 39 | bytes: 4176 on end! split: 4 | sum: 18 chunks $ node query3.js request! split:0 on response! split:232 on data! split: 2 | bytes: 2689 on data! split: 3 | bytes: 1448 on data! split: 108 | bytes: 2896 on data! split: 2 | bytes: 2896 on data! split: 3 | bytes: 2896 on data! split: 109 | bytes: 5792 on data! split: 3 | bytes: 5792 on data! split: 3 | bytes: 5792 on data! split: 108 | bytes: 10552 on data! split: 7 | bytes: 24194 on data! split: 106 | bytes: 2896 on data! split: 8 | bytes: 13864 on data! split: 5 | bytes: 22336 on data! split: 101 | bytes: 4344 on data! split: 9 | bytes: 14280 on data! split: 6 | bytes: 22879 on data! split: 100 | bytes: 4344 on data! split: 7 | bytes: 8520 on end! split: 4 | sum: 18 chunks $ node query3.js request! split:0 on response! split:395 on data! split: 1 | bytes: 4137 on data! split: 113 | bytes: 8688 on data! split: 114 | bytes: 17376 on data! split: 112 | bytes: 8688 on data! split: 4 | bytes: 1864 on data! split: 2 | bytes: 22746 on data! split: 108 | bytes: 17376 on data! split: 13 | bytes: 832 on data! split: 1 | bytes: 23784 on data! split: 99 | bytes: 4344 on data! split: 3 | bytes: 12832 on data! split: 5 | bytes: 5992 on data! split: 6 | bytes: 18824 on data! split: 100 | bytes: 10136 on data! split: 14 | bytes: 791 on end! split: 1 | sum: 15 chunks $ node query3.js request! split:0 on response! split:232 on data! split: 3 | bytes: 4137 on data! split: 111 | bytes: 8688 on data! split: 115 | bytes: 17376 on data! split: 112 | bytes: 5792 on data! split: 3 | bytes: 4760 on data! split: 18 | bytes: 22746 on data! split: 93 | bytes: 8688 on data! split: 20 | bytes: 9520 on data! split: 3 | bytes: 22336 on data! split: 91 | bytes: 11584 on data! split: 20 | bytes: 7040 on data! split: 2 | bytes: 25775 on data! split: 91 | bytes: 5792 on data! split: 1 | bytes: 4176 on end! split: 1 | sum: 14 chunks
また、大きなjpeg画像(提供:preacher_lad氏)もリクエストしてみました。
$ node query4.js request! split:0 on response! split:283 on data! split: 1 | bytes: 2430 on data! split: 138 | bytes: 5968 on data! split: 139 | bytes: 16537 on data! split: 144 | bytes: 29116 on data! split: 3 | bytes: 4018 on data! split: 132 | bytes: 22724 on data! split: 3 | bytes: 20688 on data! split: 136 | bytes: 10556 on data! split: 6 | bytes: 43196 on data! split: 134 | bytes: 14725 on data! split: 9 | bytes: 38886 on data! split: 132 | bytes: 19048 on data! split: 12 | bytes: 49134 on data! split: 126 | bytes: 8800 on data! split: 16 | bytes: 57902 on data! split: 6 | bytes: 9650 on data! split: 117 | bytes: 24773 on data! split: 17 | bytes: 23489 on data! split: 4 | bytes: 36493 on data! split: 119 | bytes: 20601 on data! split: 28 | bytes: 906 on data! split: 2 | bytes: 57785 on data! split: 6 | bytes: 3112 on data! split: 102 | bytes: 10349 on data! split: 2 | bytes: 10320 on data! split: 29 | bytes: 34251 on data! split: 5 | bytes: 17040 on end! split: 3 | sum: 27 chunks
思ったこと
※これらは「チャンク」ではありませんでした。
チャンク数は決まっていない- 何バイトで切るかも、決まってないように見える。
100ミリ秒強ごとに、どばどばっとロードし、数chunkに分けて出しているように見えるが、定かではない。- あまりよくわからない。相手サーバの設定とか回線状況とかにもよる気がする。
- 常にボディ全体にアクセスしたい場合、各
chunkをconcatした総chunk文字列を、on endのタイミングで利用する、とかいうことになるのだろうか。 - chungking express(邦題「恋する惑星」)のテーマソングがずっと流れていたが、関係ない。
はやく
何でもいいから、はやく何か作りたいです・・・