<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Web/DB プログラミング徹底解説ブログ &#187; プロトコル</title>
	<atom:link href="http://keicode.com/blog/tag/%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab/feed/" rel="self" type="application/rss+xml" />
	<link>http://keicode.com/blog</link>
	<description>Web/DB プログラミング、コンピュータ、システム開発に関する小山圭介の雑感</description>
	<lastBuildDate>Sat, 28 Aug 2010 21:19:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>SPDY (スピーディ) プロトコル (後半部) 日本語訳 12/01/2009 版</title>
		<link>http://keicode.com/blog/spdy-%e3%82%b9%e3%83%94%e3%83%bc%e3%83%87%e3%82%a3-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab-%e5%be%8c%e5%8d%8a%e9%83%a8-%e6%97%a5%e6%9c%ac%e8%aa%9e%e8%a8%b3-12012009-%e7%89%88/</link>
		<comments>http://keicode.com/blog/spdy-%e3%82%b9%e3%83%94%e3%83%bc%e3%83%87%e3%82%a3-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab-%e5%be%8c%e5%8d%8a%e9%83%a8-%e6%97%a5%e6%9c%ac%e8%aa%9e%e8%a8%b3-12012009-%e7%89%88/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 08:06:57 +0000</pubDate>
		<dc:creator>小山圭介</dc:creator>
				<category><![CDATA[SPDY プロトコル翻訳]]></category>
		<category><![CDATA[SPDY]]></category>
		<category><![CDATA[プロトコル]]></category>
		<category><![CDATA[後半部]]></category>
		<category><![CDATA[日本語訳]]></category>

		<guid isPermaLink="false">http://keicode.com/blog/?p=197</guid>
		<description><![CDATA[前回の SPDY プロトコル仕様書の翻訳前半戦に引き続き、SPDY プロトコルの仕様書 (ドラフト) の翻訳の後半戦です。プロトコルを実装しようとしない限り、あまり必要とする人はいない情報かもしれませんが・・・ (汗) # かつ、数日時間が開いてしまったので、前半戦は 11/28 版だったのに対して、後半は 12/01 版です。すみません。 翻訳の怪しいところはコメントでご指摘いただけることを祈りつつ・・・ それでは後半戦をお楽しみください。 フレーミング TCP コネクションが確立されると、クライアントとサーバーはフレーム化されたメッセージ (framed message) を交換可能になります。フレームには２種類あります。コントロールフレーム (control frame) とデータフレーム (data frame) です。フレームは常に共通の８バイトのヘッダを持っています。 第一ビットはコントロールフレームかデータフレームであるかを示すコントロールビットです。コントロールフレームはバージョン番号、フレームタイプ、フラグ及び長さを含みます。データフレームはストリーム ID、フラグ及び共通ヘッダの後に運ばれるペイロードの長さを含みます。単純なヘッダにより、フレームの読み書きを単純になります。 長さ、バージョン、型などを含む全ての整数値はネットワークバイトオーダーです。SPDY は動的サイズフレームのアラインメントの方法を強制しません。 コントロールフレーム +----------------------------------+ &#124;C&#124; Version(15bits) &#124; Type(16bits) &#124; +----------------------------------+ &#124; Flags (8) &#124; Length (24 bits) &#124; +----------------------------------+ &#124; Data &#124; +----------------------------------+ コントロールフレームフィールド: コントロールビット: &#8216;C&#8217; [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="size-full wp-image-202 aligncenter" title="SPDY プロトコル仕様書日本語訳" src="http://keicode.com/blog/wp-content/uploads/2009/12/chrome-spdy-title-2.png" alt="SPDY プロトコル仕様書日本語訳" width="400" height="95" /></p>
<p>前回の<a href="http://keicode.com/blog/spdy-%E3%82%B9%E3%83%94%E3%83%BC%E3%83%87%E3%82%A3-%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB-%E5%89%8D%E5%8D%8A%E9%83%A8-%E6%97%A5%E6%9C%AC%E8%AA%9E%E8%A8%B3-11282009%E7%89%88/"> SPDY プロトコル仕様書の翻訳前半戦</a>に引き続き、SPDY プロトコルの仕様書 (ドラフト) の翻訳の後半戦です。プロトコルを実装しようとしない限り、あまり必要とする人はいない情報かもしれませんが・・・ (汗)</p>
<p># かつ、数日時間が開いてしまったので、前半戦は 11/28 版だったのに対して、後半は 12/01 版です。すみません。</p>
<p>翻訳の怪しいところはコメントでご指摘いただけることを祈りつつ・・・</p>
<p>それでは後半戦をお楽しみください。</p>
<p></p>
<h2>フレーミング</h2>
<p>TCP コネクションが確立されると、クライアントとサーバーはフレーム化されたメッセージ (framed message) を交換可能になります。フレームには２種類あります。コントロールフレーム (control frame) とデータフレーム (data frame) です。フレームは常に共通の８バイトのヘッダを持っています。</p>
<p>第一ビットはコントロールフレームかデータフレームであるかを示すコントロールビットです。コントロールフレームはバージョン番号、フレームタイプ、フラグ及び長さを含みます。データフレームはストリーム ID、フラグ及び共通ヘッダの後に運ばれるペイロードの長さを含みます。単純なヘッダにより、フレームの読み書きを単純になります。</p>
<p>長さ、バージョン、型などを含む全ての整数値はネットワークバイトオーダーです。SPDY は動的サイズフレームのアラインメントの方法を強制しません。</p>
<h3>コントロールフレーム</h3>
<pre style="font-family:courier new;">+----------------------------------+
|C| Version(15bits) | Type(16bits) |
+----------------------------------+
| Flags (8)  |  Length (24 bits)   |
+----------------------------------+
|               Data               |
+----------------------------------+</pre>
<p>コントロールフレームフィールド:</p>
<p>コントロールビット: &#8216;C&#8217; ビットはこれがコントロールメッセージであることを示します。コントロールフレームについては、この値が常に 1 です。</p>
<p>バージョン: セッションプロトコルのバージョン番号 (現在は 1 です)</p>
<p>タイプ: コントロールフレームのタイプ。コントロールフレームは、SYN_STREAM, SYM_REPLY などです。</p>
<p>フラグ: このフレームに関わるフラグ。コントロールフレームとデータフレームのフラグは異なります。</p>
<p>長さ: 長さフィールドのあとのバイト数。これは符号なしの 24 ビット値で表します。</p>
<p>データフレーム</p>
<pre class="font-family:Courier New;">+----------------------------------+
|C|       Stream-ID (31bits)       |
+----------------------------------+
| Flags (8)  |  Length (24 bits)   |
+----------------------------------+
|               Data               |
+----------------------------------+</pre>
<p>データフレームフィールド:</p>
<p>コントロールビット: データフレームでは、この値は常に 0 です。</p>
<p>ストリーム ID: ストリームを識別するための 31 ビット値</p>
<p>フラグ: このフレームに関連したフラグ。正しいフラグは次のものです。</p>
<ul>
<li>0&#215;01 = FLAG_FIN &#8211; このストリームのハーフクローズを表します。以下のストリームハーフクローズを参照してください。</li>
</ul>
<p>長さ: 長さフィールドに続くバイト数を表す 24 ビット値。データフレームのトータルサイズは、8 バイト + &#8220;長さ&#8221; です。長さゼロのデータフレームでも構いません。</p>
<p>データ: ペイロード中の可変長フィールドです。</p>
<h2>Hello メッセージ</h2>
<p>接続が確立してから、SPDY は双方が通信の詳細を教えあうための非同期の Hello シーケンスを行います。多くのプロトコルと違って、この Hello シーケンスは任意であり、完全に非同期的に行われます。非同期であるため、接続の開始に関してラウンドトリップによる遅延を発生させません。しかし、非同期で任意であるために、双方はこのメッセージがいかなるときに到達するかもしれず、また、全く到達しないかもしれないことについて準備していなければなりません。</p>
<p>Hello シーケンスを始めるために、どちらかは HELLO コントロールフレームを送信可能です。Hello フレームは任意ですが、もし送信されるのであれば、それは送信される最初のフレームでなければいけません。Hello メッセージを受け取ったときに、Hello メッセージの応答を返信しなければいけないこともありません。従って、このメッセージは完全に参考値となります。</p>
<p>HELLO コントロールメッセージ:</p>
<pre style="font-family:Courier New;">+----------------------------------+
|1|       1          |       4     |
+----------------------------------+
| Flags (8)  |  Length (24 bits)   |
+----------------------------------+
|  Unused       |Number of entries |
+----------------------------------|
|          ID/Value Pairs          |
|             ...                  |</pre>
<p>HELLO メッセージフィールド:</p>
<p>コントロールビット: このメッセージのコントロールビットは常に 1 です。</p>
<p>バージョン: SPDY バージョン番号</p>
<p>タイプ: HELLO メッセージのメッセージタイプは 4 です。</p>
<p>未使用: 将来のために 16 ビットが未使用です。</p>
<p>エントリー数: メッセージ中の 識別子/値 の数を表す 16 ビット値</p>
<p>ID: 32 ビットの ID 番号。次の ID が妥当です:</p>
<ul>
<li>1 &#8211; HELLO_BANDWIDTH_TO_YOU この値によって送信者はこのチャネルで期待されるアップロード帯域幅を送信できます。この値は概算値です。この値は、期待される最大アップロードチャネルキャパシティとして送信者が予測している数値を、一秒間あたりのキロバイト数として表した整数値です。</li>
<li>2 &#8211; HELLO_BANDWIDTH_FROM_YOU この値によって送信者はこのチャネルで期待されるダウンロード帯域幅を送信できます。この値は概算値です。この値は、期待される最大ダウンロードチャネルキャパシティとして送信者が予測している数値を、一秒間あたりのキロバイト数として表した整数値です。</li>
<li>3 &#8211; HELLO_ROUND_TRIP_TIME 送信者は、このチャネルで期待されるラウンドトリップ時間を送ることが可能です。このラウンドトリップ時間は、このクライアントからリモートに対してコントロールフレームを送信して、応答を受け取るための最小時間として定義されます。この値はミリ秒で表現します。</li>
<li>4 &#8211; HELLO_MAX_CONCURRENT_STREAMS これによって許容される最大同時ストリーム数をリモートに送信可能です。既定では制限はありません。実装者は、この値を１００以下にはしないようにしてください。</li>
</ul>
<p>値: 32 ビット値</p>
<p>将来的にクライアントサーバー通信を改善できるように、メッセージは意図的に拡張可能にしてあります。送信者はいかなる種類の識別子/値も送信する必要はありません。送信者は伝達するために正確な値を持つ識別子/値のみを送らなければなりません。複数の 識別子/値ペアが送信されたときは、小さな値の ID から大きな値の ID の順序で送信されるべきです。</p>
<h2>ストリーム</h2>
<p>ストリームは複数のフレームに分割される、独立した双方向のデータです。ストリームは、クライアント、サーバーのいずれ側からでも作成可能であり、他のストリームと交互に行き来するデータを送信でき、さらにキャンセルも可能です。HTTP でストリームを使う場合は、単一の HTTP 要求/応答が単一のストリームを占めるようにし、そのストリームはそれに続く要求で再利用されないようにします。これはストリームはラウンドトリップなで、独立的に作成可能であるからです。</p>
<p>ストリームの初期化にて、ストリームは双方が相手側のエンドポイントに固定長の名前/値ペアのリストを送信可能です。</p>
<h3>ストリーム生成</h3>
<p>ストリームは、タイプを SYN_STREAM (1) にセットしたコントロールパケットを送ることによって作成可能です。もしサーバーがストリームを開始した場合、ストリーム ID は偶数でなければいけません。クライアントがストリームを開始する場合は、ストリーム ID は奇数です。0 は正しいストリーム ID ではありません。接続の双方からのストリーム ID は、新しいストリームを作るたびに、単調に増加させなければなりません。例えば、ストリーム 2 はストリーム 3 の後に作成できますが、ストリーム 7 はストリーム 9 の後に作成してはいけません。</p>
<p>SYN_STREAM フレームの受取り確認としては、受け取り手は SYN_PREPLY フレームで応答します。クライアントは、データフレームを送る前に SYN_REPLY を待ち受ける必要はありません。</p>
<p>もし SYN_STREAM を受け取ったエンドポイントが、新しいストリームを作成することを望まないならば、直ちに FIN_STREAM コントロールフレームで応答することも可能です。しかしながら、ストリームを開始したエンドポイントはそのストリーム上で既にデータを送信してきているかもしれないことに注意してください。このデータは無視しなければなりません。</p>
<p>SYN_STREAM コントロールメッセージ:</p>
<pre style="font-family:Courier New;">  +----------------------------------+
  |1|       1          |       1     |
  +----------------------------------+
  | Flags (8)  |  Length (24 bits)   |
  +----------------------------------+
  |X|          Stream-ID (31bits)    |
  +----------------------------------+
  | Pri | Unused    |   NV Entries   |
  +----------------------------------|
  |     Name/value header block      |
  |             ...                  |</pre>
<p>SYN_STREAM メッセージフィールド:</p>
<p>フラグ (Flags): このフレームに関するフラグ。妥当なフラグは以下の通り：</p>
<ul>
<li>0&#215;01 = FLAG_FIN &#8211; そのストリームのハーフクローズを示します。これがセットされると、送信者はこのストリーム上でこれ以上データを送信しません。</li>
</ul>
<p>長さ (Length): 長さフィールドの後に続くバイト数を表す符号なし 24 ビット値です。SYN_STREAM フレームの合計サイズは 8 バイト + 長さフィールドの値です。このフレームの長さは、8 かそれ以上でなければいけません。</p>
<p>優先度 (Priority): 2 ビットの優先度フィールド。もしエンドポイントが複数のストリームを開始した場合、優先度フィールドがどのストリームに優先順位を与えればよいか決めます。サーバーは厳密にその優先度に従うことを必要とされてはいませんが、最善の努力 (best-effort) をすることが想定されています。0 は最低の優先順位を表し、3 が最高の優先順位です。The highest-priority data is that which is most desired by the client.</p>
<p>未使用: 14 ビットの未使用のスペース。将来的な利用のため予約されています。</p>
<p>NV エントリー: (16 ビット) 続く名前/値のペアの数。</p>
<p>名前/値ブロック (Name/Value Block) は以下に説明しています。</p>
<p>SYN_REPLY コントロールメッセージ:</p>
<pre style="font-family:Courier New;">  +----------------------------------+
  |1|        1        |        2     |
  +----------------------------------+
  | Flags (8)  |  Length (24 bits)   |
  +----------------------------------+
  |X|          Stream-ID (31bits)    |
  +----------------------------------+
  | Unused        |    NV entries    |
  +----------------------------------|
  |     Name/value header block      |
  |              ...                 |</pre>
<p>SYN_REPLY メッセージフィールド:</p>
<p>フラグ: このフレームに関するフラグ。正しいフラグは以下の通り：</p>
<ul>
<li>0&#215;01 &#8211; FLAG_FIN これはストリームのハーフクローズを示します。これがセットされると、送信者はこのストリーム上でこれ以上データを送信しません。</li>
</ul>
<p>長さ (Length): 長さフィールドの後に続くバイト数を表す符号なし 24 ビット値です。SYN_STREAM フレームの合計サイズは 8 バイト + 長さフィールドの値です。このフレームの長さは、8 かそれ以上でなければいけません。</p>
<p>未使用: 16 ビットの未使用領域。将来の利用のために予約されています。</p>
<p>NV エントリ: (16 ビット) これに続く名前/値ペアの数</p>
<p>名前/値ブロックについては、以下に説明しています。</p>
<h3>名前/値ヘッダブロックフォーマット</h3>
<p>SYN_STREAM と SYN_REPLY フレームの両方共に、名前/値ヘッダブロック (Name/Value Header Block) を含みます。要求と応答の両方で使用されるヘッダブロックは同一です。リストの最後に容易に追加できるように設計されています。また、受け取り手が容易に解析できるように設計されています。それぞれの数値は 2 バイトです。</p>
<pre style="font-family:Courier New;">  +----------------------------------+
  |     Length of name (int16)       |
  +----------------------------------+
  |           Name (string)          |
  +----------------------------------+
  |     Length of value  (int16)     |
  +----------------------------------+
  |          Value   (string)        |
  +----------------------------------+
  |           (repeats)              |</pre>
<p>それぞれのヘッダ名は少なくともひとつの値を持たなければなりません。それぞれの名前及び値の長さは 0 より大きくなければなりません。</p>
<p>ヘッダ名の重複は許されません。二つの同一の名前のヘッダを送信するためには、一つのヘッダーに二つの値を設定して送信します。この値は単一の NUL (0) バイトによって分割されます。</p>
<p>文字列は UTF8 エンコードを行い、NUL 終端ではありません。</p>
<p>名前/値ペアは gzip で圧縮されます。ひとつのコネクション上に、単一方向の、全ての名前/値ペアの名前に対する単一の gzip ストリーム (コンテキスト) があります。このストリームは以下の辞書によって初期化されます（改行無し）：</p>
<pre style="font-family:Courier New;">optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-
languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi
f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser
-agent10010120020120220320420520630030130230330430530630740040140240340440
5406407408409410411412413414415416417500501502503504505accept-rangesageeta
glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic
ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran
sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati
oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo
ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe
pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic
ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1
.1statusversionurl</pre>
<h2>ストリームデータ交換</h2>
<p>ストリームが作られると、それはどちらの方向にも任意の量のデータを送るために使用できます。どちらかが送信を終了したら、FIN_FLAG をセットしたフレームを送信できます (TCP 接続の切断を参照してください）</p>
<h3>ストリーム・ハーフクローズ</h3>
<p>ストリームの片方が FLAG_FIN フラグをセットしたコントロールフレーム、またはデータフレームを送信したら、そのストリームはその側からハーフクローズされたとみなされます。FLAG_FIN の送信者は、このストリーム上でこれ以上データを送信しないことを表しています。両者がハーフクローズされると、そのストリームはクローズとみなされます。</p>
<h3>ストリーム・クローズ</h3>
<p>ストリームを終了する方法は３つあります。通常終了 (normal termination)、異常終了 (abrupt termination)、そして、TCP 接続切断 (TCP connection teardown) です。</p>
<h4>通常終了</h4>
<p>通常終了は、ストリームの双方が、ストリームをハーフクローズとしたときに発生します。</p>
<h4>異常終了</h4>
<p>クライアントまたはサーバーのいずれかは、いつでも FIN_STREAM コントロールパケットを送信可能です。FIN_STREAM の応答として、双方共にそのストリームから受け取ったデータを無視しなければならず、また、双方共にそのストリームへのデータ送信を停止しなければなりません。FIN_STREAM はストリームの異常停止のために用意されています。</p>
<p>FIN_STREAM コントロールフレーム:</p>
<pre style="font-family:Courier New;">  +-------------------------------+
  |1|       1        |      3     |
  +-------------------------------+
  | Flags (8)  |         8        |
  +-------------------------------+
  |X|          Stream-ID (31bits) |
  +-------------------------------+
  |          Status code          |
  +-------------------------------+</pre>
<p>FIN_STREAM メッセージフィールド</p>
<p>フラグ (Flags): このフレームに関連したフラグ。正しい値は次の通りです。</p>
<ul>
<li>0&#215;01 = FLAG_FIN これがセットされると、このストリーム上で送信者はこれ以上データを送信しません。上記ストリームハーフクローズを参照してください。</li>
</ul>
<p>長さ (Length): 長さフィールドに続くバイト数を表す 24 ビット値。FIN_STREAM コントロールフレームに対しては、この値は常に 8 です。</p>
<p>ステータスコード (Status code): (32 ビット) ストリームが終了する理由を示します。以下のステータスコードが定義されています。</p>
<ul>
<li>1 &#8211; PROTOCOL_ERROR これは一般的なエラーで、特定のエラーが利用できない場合にのみ使います。このエラーを受け取った側は、セッション全体を終了 (abort) して、通常ユーザーにエラーを返します。</li>
<li>2 &#8211; INVALID_STREAM アクティブではないフレームを受信した場合に返します。このエラーの受信者は通信エラーを記録します。</li>
<li>3 &#8211; REFUSED_STREAM これはストリーム上で処理される前にストリームが拒否されたことを示します。非 indepotent メソッドに対しては、これは要求は再試行可能であることを意味します。</li>
</ul>
<p>注: FIN_STREAM では 0 は正しいステータスコードではありません。</p>
<p>TODO (やること) &#8211; より詳細のエラーを定義する。</p>
<h4>TCP 接続の切断</h4>
<p>もし終了していないストリームがアクティブなうちに (すなわち、そのストリームに対して FIN_STREAM が送受信されていない場合)、TCP コネクションが切断された場合、エンドポイントはそのストリームは異常に割り込みされ、不完全な状態になっているかもしれないことを想定しなければなりません。</p>
<p>クライアントまたはサーバーが、既に切断されているストリーム上からデータを受け取った場合、切断後に受け取ったデータは無視しなければなりません。</p>
<h2>データフロー</h2>
<p>SPDY は複数の論理的なストリームで多重化していますが、TCP は単一のデータストリームを提供しているので、クライアントとサーバーが同時セッションでデータメッセージを交換することは重要です。</p>
<p>実装者は小さいチャンクでデータを送ると、ブラウザがメタデータを早く解析でき、レイアウトを最終化できるために、エンドユーザーの遅延を低めることになることに注意してください。大きなチャンクでデータを送ることは、帯域幅の効率を若干高めるものの、多くのリソースを持つページにおいてユーザーの体験をスローダウンさせることになります。</p>
<h3>他のコントロールフレーム</h3>
<h4>NOOP</h4>
<p>NOOP コントロールフレームは非制御フレームです。これはクライアントあるいはサーバーから送信可能です。NOOP フレームの受信者は単にそれを無視するだけです。</p>
<p>注: このコントロールフレームは最終的には削除されるかもしれません。これは実験的な目的で実装されました。</p>
<p>NOOP コントロールメッセージ:</p>
<pre style="font-family:Courier new;">  +----------------------------------+
  |1|       1          |       5     |
  +----------------------------------+
  | 0 (Flags)  |    0 (Length)       |
  +----------------------------------+</pre>
<p>コントロール ビット: このメッセージにおけるコントロールビットは常に 1 です。</p>
<p>バージョン: SPDY のバージョン番号</p>
<p>タイプ: NOOP メッセージのメッセージタイプは 5 です。</p>
<p>長さ: このフレームはデータを運びません。長さは常に 0 です。</p>
<h4>PING</h4>
<p>PING コントロールフレームは、送信者からの最小ラウンドトリップ時間を計測するための仕組みです。これはクライアントあるいはサーバーいずれかから送信可能です。PING フレームの受信者は、可能な限り直ちに同一のフレームを送信します (もし送信を待っている他のデータがあった場合も、PING は最高の優先度とするべきです)。送信者が送信した PING はユニークな ID を使うべきです。</p>
<p>注: このコントロールフレームは最終的に削除されるかもしれません。これは実験の目的で実装されました。</p>
<p>PING コントロールメッセージ:</p>
<pre style="font-family:Courier New;">  +----------------------------------+
  |1|       1          |       6     |
  +----------------------------------+
  | 0 (flags) |     4 (length)       |
  +----------------------------------|
  |            32-bit ID             |
  +----------------------------------|</pre>
<p>コントロールビット: このメッセージのコントロールビットは常に 1 です。</p>
<p>バージョン: SPDY のバージョン番号</p>
<p>タイプ: PING メッセージのメッセージタイプは 6 です。</p>
<p>長さ: このフレームは常に 4 バイトの長さです。</p>
<p>ID: ピングのユニーク ID</p>
<p>注: もし送信者が可能な PING ID を使った場合 (つまり、 2 の 32 乗の ID を送った場合)、「折り返し」て ID を再利用しても良いです。</p>
<h4>GOAWAY</h4>
<p>GOAWAY コントロールフレームは、リモート側に対してこのセッションをこれ以上使わないことを伝えるための仕組みです。これはクライアント、サーバー両方から送られる可能性があります。送信されると、その送信者はこのセッション上に新しいストリームを初期化しないことになります。GOAWAY フレームの受信者は、新しい要求のため新しいセッションを確立することは出来ますが、このセッション上に追加の要求を送信してはいけません。このメッセージの目的は、以前に確立していた要求の処理を続けさせつつ、サーバーに行儀良く、新しい要求を受け取ることを止めさせ （多くの場合、リブートやメンテナンスのために）ることです。</p>
<p>要求を送信するクライアントと GOAWAY メッセージを送信するサーバーの間には、特有の競合状態があります。この状況に対応するために、GOAWAY メッセージはこのセッションで受け入れられた最後のストリームを表すストリーム ID を含んでいます。このストリーム ID の後に、クライアントがセッションの要求を発行したならば、それらはサーバーによって受け入れられず、クライアントの裁量において、後ほど再発行されます。</p>
<p>注: このコントロールフレームは最終的に削除されるかもしれません。これは実験の目的で実装されました。</p>
<p>注: (mnot@mnot.org は必須の GOAWAY がセッションを行儀良く閉じるのに役に立つだろうと提言しています。もしあるセッション上での最後の要求が POST であったとして、サーバーが閉じていたとしたら、クライアントはリクエストが送信されたかどうかわかりません。閉じる前に GOAWAY を要求することは、クライアントに対して、クライアントに対して、どの要求が処理されたか、されていないか通知することになります)</p>
<p>GOAWAY コントロールメッセージ:</p>
<pre style="font-family:Courier New;">  +----------------------------------+
  |1|       1          |       7     |
  +----------------------------------+
  | 0 (flags) |     4 (length)       |
  +----------------------------------|
  |       Last-good-stream-ID        |
  +----------------------------------|</pre>
<p>コントロールビット: このメッセージに対するコントロールビットは常に 1 です。</p>
<p>バージョン: SPDY のバージョン番号</p>
<p>タイプ: GOAWAY メッセージのメッセージタイプは 7 です。</p>
<p>長さ: このフレームは常に 4 バイト長です。</p>
<p>Last-good ストリーム ID: GOAWAY メッセージの送信者によって、受け入れられた最後のストリーム ID</p>
<h4>SUBRESOURCE</h4>
<p>サブリソース (SUBRESOURCE) コントロールフレームは、任意のコントロールフレームであり、受信者に必要なリソースを教えるために使われます。もし名前/値ペア内の URL とメソッドが、そのストリーム ID に関連付けされたものと一致しないならば、このコントロールメッセージは無視されなければなりません。</p>
<p>コントロールフレーム</p>
<pre style="font-family:Courier New;">  +----------------------------------+
  |C| Version(15bits) |      8       |
  +----------------------------------+
  | Flags (8)  |  Length (24 bits)   |
  +----------------------------------+
  |0| Stream id (31 bits)            |
  |----------------------------------|
  |  Unused (16 bits) | NV Entries   |
  |----------------------------------|
  | Key value pairs                  |
  +----------------------------------+</pre>
<p>長さ: 長さフィールドの後に続くバイト数を表す符号なしの 24 ビット値。SUBRESOURCE フレームの合計長は 8 バイト + 長さです。このフレームの長さは、8 と同じかそれ以上でなければなりません。</p>
<p>ストリーム ID (Stream-id) はサブリソースが関連付けされたストリームのストリーム ID です。</p>
<p>NV エントリ: これに続く名前/値ペアの数</p>
<p>名前/値ブロックは SYN_REPLY と同じです。しかし、url と method は必須フィールドです。</p>
<p>もし送信者が SUBRESOURCE コントロールフレームを使って、クライアントにストリームが作成される (X-Associated-Content) ことを教えたならば、SUBRESOURCE メッセージは、受信者が追加リソースを見つけられるようにデータフレームよりも先に送信されなければならない。</p>
<h2>参考資料</h2>
<p>タイトルの通り、この日本語訳資料は 2009年12月1日時点のドラフトを元に作成してあります。</p>
<p>最新版は<a href="http://dev.chromium.org/spdy/spdy-protocol">本家 Chromium プロジェクトの SPDY プロトコル仕様書ページ</a>をご覧ください。</p>
]]></content:encoded>
			<wfw:commentRss>http://keicode.com/blog/spdy-%e3%82%b9%e3%83%94%e3%83%bc%e3%83%87%e3%82%a3-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab-%e5%be%8c%e5%8d%8a%e9%83%a8-%e6%97%a5%e6%9c%ac%e8%aa%9e%e8%a8%b3-12012009-%e7%89%88/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SPDY (スピーディ) プロトコル (前半部) 日本語訳 11/28/2009版</title>
		<link>http://keicode.com/blog/spdy-%e3%82%b9%e3%83%94%e3%83%bc%e3%83%87%e3%82%a3-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab-%e5%89%8d%e5%8d%8a%e9%83%a8-%e6%97%a5%e6%9c%ac%e8%aa%9e%e8%a8%b3-11282009%e7%89%88/</link>
		<comments>http://keicode.com/blog/spdy-%e3%82%b9%e3%83%94%e3%83%bc%e3%83%87%e3%82%a3-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab-%e5%89%8d%e5%8d%8a%e9%83%a8-%e6%97%a5%e6%9c%ac%e8%aa%9e%e8%a8%b3-11282009%e7%89%88/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 17:06:51 +0000</pubDate>
		<dc:creator>小山圭介</dc:creator>
				<category><![CDATA[SPDY プロトコル翻訳]]></category>
		<category><![CDATA[2009版]]></category>
		<category><![CDATA[SPDY]]></category>
		<category><![CDATA[プロトコル]]></category>
		<category><![CDATA[前半部]]></category>
		<category><![CDATA[日本語訳]]></category>

		<guid isPermaLink="false">http://keicode.com/blog/?p=190</guid>
		<description><![CDATA[先日、Google が SPDY プロトコル (スピーディプロトコル) を発表しました。 私も興味があったので、その仕様書を読みつつ日本語訳を書いてみました。とりあえず、概要 (overview) から接続 (connections) までを翻訳してます。スピーディの特徴を把握することは出来ると思います。 続きは、私が余力があればいずれ書きたいと思います。どなたか書かれましたら教えていただければと思います。 SPDY プロトコル 概要 現行の HTTP のボトルネックのひとつは、HTTP は同時並行性 (concurrency) に関して複数の接続にのみ依存しているということです。これは、接続開始のための余計なラウンドトリップ、開始の遅さ、単一のサーバーに大量の接続を開始することを避けるためのクライアントによる接続制限 (訳注: constant rationing はこのことを指すでしょうか) を含むいくつかの問題を引き起こします。HTTP パイプライニング (pipelining) はそのラインの先頭にてリクエストがブロックされるかもしれないので役に立たず、それに加えて多くのプロキシはパイプライニングをあまりよくサポートしていません。多くの接続を作成しようとするアプリケーションは、ドメイン毎の接続スロットリングを回避するために、多くのサブドメインを作成します。 SPDY はこのような現行の Web アプリケーションに関わるアプリケーション層の問題を解決することを目的とします。同時に Web アプリケーションを書く人の観点でいえば、ごくわずかの変更かあるいは全く変更がないようにします。 簡単に言えば、SPDY は単一の TCP 接続に、多重化された複数の同時平行ストリームのためのフレーミング層 (a framing layer for multiplexing multiple, concurrent streams) を追加します。フレーミング層は HTTP 的な要求応答ストリームに最適化されます。 SPDY セッションは HTTP と比較して、三つの基本的な改良を施します。 多重化された要求. [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-192" title="スピーディプロトコル翻訳前半戦" src="http://keicode.com/blog/wp-content/uploads/2009/11/chrome-spdy-title-1.png" alt="スピーディプロトコル翻訳前半戦" width="400" height="95" /></p>
<p>先日、Google が <a href="http://dev.chromium.org/spdy/spdy-protocol">SPDY プロトコル (スピーディプロトコル)</a> を発表しました。</p>
<p>私も興味があったので、その仕様書を読みつつ日本語訳を書いてみました。とりあえず、概要 (overview) から接続 (connections) までを翻訳してます。スピーディの特徴を把握することは出来ると思います。</p>
<p>続きは、私が余力があればいずれ書きたいと思います。どなたか書かれましたら教えていただければと思います。</p>
<p></p>
<h2>SPDY プロトコル</h2>
<h2>概要</h2>
<p>現行の HTTP のボトルネックのひとつは、HTTP は同時並行性 (concurrency) に関して複数の接続にのみ依存しているということです。これは、接続開始のための余計なラウンドトリップ、開始の遅さ、単一のサーバーに大量の接続を開始することを避けるためのクライアントによる接続制限 (訳注: constant rationing はこのことを指すでしょうか) を含むいくつかの問題を引き起こします。HTTP パイプライニング (pipelining) はそのラインの先頭にてリクエストがブロックされるかもしれないので役に立たず、それに加えて多くのプロキシはパイプライニングをあまりよくサポートしていません。多くの接続を作成しようとするアプリケーションは、ドメイン毎の接続スロットリングを回避するために、多くのサブドメインを作成します。</p>
<p>SPDY はこのような現行の Web アプリケーションに関わるアプリケーション層の問題を解決することを目的とします。同時に Web アプリケーションを書く人の観点でいえば、ごくわずかの変更かあるいは全く変更がないようにします。</p>
<p>簡単に言えば、SPDY は単一の TCP 接続に、多重化された複数の同時平行ストリームのためのフレーミング層 (a framing layer for multiplexing multiple, concurrent streams) を追加します。フレーミング層は HTTP 的な要求応答ストリームに最適化されます。</p>
<p>SPDY セッションは HTTP と比較して、三つの基本的な改良を施します。</p>
<ul>
<li>多重化された要求. 単一の SPDY 接続上で同時に発行できる要求数に上限はありません。単一のチャネル上で複数のリクエストが交互の行き来 (訳注: interleaved) するので、TCP の効率はずっと高まります。</li>
<li>優先順位付けされた要求. クライアントはあるリソースを先に到達させることを要求することが可能です。これによって優先度の高い要求が待ち状態でありながら、重要でないリソースによってネットワークチャネルが混雑した状態になることを防ぐことが出来ます。</li>
<li>圧縮されたヘッダ. 今日のヘッダは HTTP ヘッダを形作る大量の冗長なデータを送信しています。単一のウェブページは 50 あるいは 100 の従属的なリクエスト (subrequest) を必要とする場合があるので、このデータは重要です。ヘッダを圧縮することで HTTP と比べて待ち時間と大域幅を大幅に節約できます。</li>
</ul>
<p>注意していただきたいのは、多くの部分で SPDY は既存の HTTP の特徴のセマンティクスをそのまま残そうとしていることです。クッキー、ETag、Vary ヘッダ、Content-Encoding ネゴシエーションなどの全ての機能は、HTTP と全く同様に機能します。SPDY はネットワーク上でデータが記述される方法のみを置き換えるのです。</p>
<h2>定義</h2>
<ul>
<li>接続 (connection): 二つのエンドポイントの間の TCP レベルコネクション</li>
<li>エンドポイント (endpoint): 接続のクライアントあるいはサーバーのどちらか</li>
<li>セッション (session): フレーム化されたデータチャンクの連続 (訳注: a framed sequence of data chunks) フレームは SPDY フレームとして定義されます。以下のフレーム化 (Framing) を参照してください。</li>
<li>ストリーム (stream): 単一の SPDY セッション内にて、仮想的なチャネルをわたるバイトの双方向の流れ。</li>
</ul>
<h2>HTTP からの主な相違点</h2>
<p>SPDY は現行の Web ベースのアプリケーションと可能な限り互換性を保つことを意図しています。これはすなわち、サーバーのビジネスロジックあるいはアプリケーション API の観点からは、何も変更されないことを意味します。これを達成するために、アプリケーション要求及び応答のヘッダーセマンティクスはそのまま保持されます。SPDY は &#8220;セッション&#8221; を導入しますが、これは HTTP アプリケーション層と TCP トランスポートの間に入り、データの流れを制御します。この &#8220;セッション&#8221; は HTTP の要求-応答ペアと同種のものです。以下に SPDY と HTTP の違いを示します。</p>
<h3>要求</h3>
<p>新しい要求を開始するために、クライアントはまず新しい SPDY セッションを作成します。セッションがひとたび作られれば、そのクライアントは要求を運ぶための新しい SPDY ストリームを作ることが可能になります。ストリームを作成することの一部は、HTTP ヘッダブロックを送信することです。SPDY での HTTP ヘッダブロックは現行の HTTP ヘッダブロックとほとんど変わりありません。変更点は以下の点です。</p>
<ul>
<li>要求の第一行は、他の HTTP ヘッダのように、名前/値ペアへと折り畳まれません。第一行のフィールドの名前は <span style="color: #008000;">method</span>, <span style="color: #008000;">url</span>, <span style="color: #008000;">version </span>です。これらのキーは必須です。url は完全に修飾された URL であり、プロトコル、ホスト、ポート及びパスを含みます。</li>
<li>ヘッダー名の重複は許されません。</li>
<li>ヘッダー名は全て小文字で表記されます。</li>
<li><span style="color: #008000;">Connection </span>と <span style="color: #008000;">Keep-Alive</span> は無効となり、存在しても無視されます。</li>
<li>クライアントは <span style="color: #008000;">Accept-Encoding: gzip</span> をサポートすることが要求されます。ボディのエンコーディングを指定しないクライアントは、サーバーから gzip エンコードされたデータを受け取ります。</li>
<li>&#8220;host&#8221; ヘッダーは無視されます。HTTP URL の ホスト:ポート 部が最終的なホストになります。</li>
<li>ユーザーエージェントは、gzip と deflate 圧縮をサポートすること期待されます。ユーザーエージェントから送信された Accept-Encoding によらず、サーバーはいつでも gzip あるいは deflate を選択できます。</li>
<li>POST 固有の変更
<ul>
<li>POST 要求はポストの一部としてデータストリームを含むことが期待されます。以下のデータフローを参照。</li>
<li><span style="color: #008000;">Content-Length</span> は単なるデータ長の参考値です (これによってプログレスメータが機能できます)</li>
<li>チャンクエンコーディングはもはや有効ではありません。</li>
<li>POST データストリームは長さ 0 のデータフレームで終了します。</li>
</ul>
</li>
</ul>
<h3>応答</h3>
<p>HTTP 要求に応答する時は、サーバーはクライアントによって作成された SPDY ストリームを使ってデータフレームを送信します。ヘッダーブロックにボディ部が続く構成であるという点においては、レスポンスは HTTP/1.1 と似ています。しかしながら、いくつか注目すべき変更があります。</p>
<ul>
<li>レスポンスステータス行は、他の HTTP ヘッダーのようには名前/値のペアに折り畳まれません。ステータス行の名前は <span style="color: #008000;">status </span>と <span style="color: #008000;">version </span>です。これらのキーは必須です。</li>
<li>もし SPDY 応答が SYN_STREAM の前に発生したなら、それはパラメータを含みます。そのパラメータはクライアントに、このレスポンスを受け取ることになったリクエストの情報を 、<span style="color: #008000;">url </span>及び <span style="color: #008000;">method </span>キーによって含みます。</li>
<li>ヘッダー名は全て小文字で表記されます。</li>
<li><span style="color: #008000;">Connection </span>と <span style="color: #008000;">Keep-Alive</span> レスポンスヘッダーはもはや無効です。</li>
<li><span style="color: #008000;">Content-Length</span> は単なる長さのアドバイザリとして扱われます。</li>
<li>チャンクエンコーディングはもはや無効です。</li>
<li>ヘッダー名の重複は許されません。</li>
</ul>
<h2>接続</h2>
<p>SPDY セッションの最初の実装は TCP の上で動作します。これは今日の HTTP が機能する仕組みと同様です。クライアントは TCP 接続の開始者であることを期待されています。TCP 上で動作するので、信頼性のある通信を確保できます。HTTP とは異なり、SPDY による全ての接続は永続性のある接続になります。HTTP 接続ヘッダーは適用されません。</p>
<p>最高のパフォーマンスのため、ユーザーが現在の接続で参照している全てのページから外部へ出て行くかサーバーが接続を閉じるまでは、クライアントは接続を閉じないことを期待されます。サーバーは可能な限り接続を開いておくようにしますが、必要ならば動きのないアイドル状態の接続を切断することは可能です。</p>
<h2>参考資料</h2>
<p>タイトルの通り、この日本語訳資料は 2009年11月28日時点のドラフトを元に作成してあります。</p>
<p>最新版は<a href="http://dev.chromium.org/spdy/spdy-protocol">本家 Chromium プロジェクトの SPDY プロトコル仕様書ページ</a>をご覧ください。</p>
]]></content:encoded>
			<wfw:commentRss>http://keicode.com/blog/spdy-%e3%82%b9%e3%83%94%e3%83%bc%e3%83%87%e3%82%a3-%e3%83%97%e3%83%ad%e3%83%88%e3%82%b3%e3%83%ab-%e5%89%8d%e5%8d%8a%e9%83%a8-%e6%97%a5%e6%9c%ac%e8%aa%9e%e8%a8%b3-11282009%e7%89%88/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
