class: title, smokescreen, shelf, no-footer # TCP<br>(Transmission Control Protocol) <div class=footnote> <small><small> </small></small> </div> <div class=digest-begin-01></div> --- class: img-right,compact # TCP: 信頼性のあるデータストリーム通信を提供します <div class=footnote> <small><small> </small></small> </div> ![height240px](images/telephone_kokusai_denwa.png) ![height240px](images/sweets_tokoroten_tentsuki.png) ![height240px](images/kids_nagashisoumen.png) ![height240px](images/kawa.png) <small> - END-TO-ENDで信頼性のあるデータ転送の仕組みを提供します。 地球の反対側まで20,000kmあろうとも(速度はともかく)通信できます - **データストリーム**はTCPによってパケット群に分割され転送されます - データストリームとは? ... <br> 転送するデータに特定の構造は仮定しません。 **ところてん**もしくは**流しそうめん**のように、 入れたものがバイト単位で反対側から次々と出てくるイメージです (注意: TCPでは同じ通信路で返事も返ってくるため、 一方通行に聞こえる**流しそうめん**は少しよくない例えですが、 ストリーム(流れ)のイメージとしては良いでしょう) </small> --- class: img-right,compact # TCP: 信頼性 <div class=footnote> <small><small> (脚注) 本当にいろいろな品質のネットワークがあるので、 複雑なリカバリができないと障害時や僻地との通信は難しい。 どんな品質でも接続し続けられることが本来の主目標と考えられます (現実とずれてきている...) </small></small> </div> ![](images/tcp-reliable.png) - 論理的な(仮想)通信路(**コネクション**)を構築し、その上でパケットを転送します。 **コネクション指向**とも呼ばれます。 逆に後述のUDPは**コネクションレス** - つねに通信の状態をモニタし、エラー訂正などはTCPが担当します (アプリケーションはエラーに気づきません) - **パケットの損傷、紛失、重複、順序の乱れを修復**します。 必要ならパケットを**再送**します - 状態があり、それをモニタしているわけで、 つまりTCPは**ステートフル**なプロトコルの例です --- class: img-right,compact # TCP: フローコントロール <div class=footnote> <small><small> (脚注) 送れそうなら、どんどん送ります(転送速度をあげます) </small></small> </div> ![](images/tcp-reliable.png) - **フローコントロール**(流量調節) - 相手ホストの忙しさ(仕事量)の具合や回線品質によって送信頻度を自動的に調節しています - (スライドの最後の方(中間試験範囲外)で基本動作を少し解説しています) --- class: img-right,compact # TCP: TCPとIPはコンビです <div class=footnote> <small><small> (脚注1) 「パケットを落とす」という表現があります (脚注2) IPは普通郵便(その家の郵便受けには入れますが相手に届いているかは未確認)、 TCPは書留(相手に届いたことまで確認する)というイメージはどうでしょうね? </small></small> </div> ![](images/tcp-reliable.png) - TCPはIPとコンビで動作します - だからTCP/IPというセットの名称 - **誰(アプリ)宛**に渡すのか?は**TCP(トランスポート層)が面倒を見ます** - **IPは住所まで(だけ)**の面倒を見ます - IPは転送途中で何かあっても気にしませんので、 きちんと**データが届いているかはTCPが気にかけます** --- class: img-right,compact # TCP: 多重化(multiplexity) <div class=footnote> <small><small> (脚注) 一つのWWWサーバに、 あるPC上から複数のアプリケーション(クライアント)が接続している場合、 クライアントのポート番号以外は、すべて同じになります i.e. 図の青線と赤線の通信では、 (サーバのIPアドレス,サーバのポート,クライアントのIPアドレス)の3つ組は同じですが、 クライアントのポートだけ異なります </small></small> </div> ![](images/tcp-multiplexity.png) - 多重化(multiplexity) - ポート番号とIPアドレスの対で通信路を区別するので、 ホスト間で同時に複数のTCP通信路を利用可能 - **サーバのIPアドレス,サーバのポート(80/tcp),クライアントのIPアドレス,クライアントのポート(ランダム)**の4つの情報の組で識別できます --- class: img-right,compact # データストリーム <!-- ![height240px](images/kids_nagashisoumen.png) --> ![width240px](images/kawa.png) ![width240px](images/money_tsuchou_cashcard.png) ![height240px](images/CC0_Ibm_punch_card.png) - 入力したデータが反対側から**1オクテット**(8ビット=1バイト)ずつ出てきます - 改行などは特別なコードを決めてありエディタなどが理解しています (ファイルを表現するための取り決め) - 例: Unixファイルの改行(line feed) <br> **012**(8進数) **0A**(16進数) - 例: ストリームの反対の例として1行80文字制限というデータ構造(右図の下) - 大昔のpunchcardでprogramming - データが無いところは空白?...非効率 - 紙幣と同じ機材が使いまわせそう - 印刷を考えると便利そう(適材適所?) <div class=footnote> <small><small> (注)1オクテットという表現: 昔のコンピュータでは1バイトが8ビットとは限らないため </small></small> </div> --- class: img-right,compact # パケットへの分割 <div class=footnote> <small><small> (脚注) ソケット(socket) ... ネットワークのプログラミングでは、 いつもの標準入出力(e.g. STDIN,STDOUT)と異なるsocketという入出力機構を使います。 このためソケットプログラミングとも呼ばれます。 BSD UnixがTCP/IPを実装したときに、この仕組みを作りました </small></small> </div> ![](images/tcp-reliable.png) <small> - データストリームはTCPによってパケット群に分割され転送されます (右図の箱の列を見よ) - アプリケーションは任意の長さのデータを送信/受信できます(**socket**への入出力) - TCPがデータをある長さ(**セグメント**サイズ)に分割して送信し、 (受信側で)再構成しています - セグメントサイズはTCPより下の層次第で可変です(だいたい1400バイト前半が多いか?) - セグメントはTCPヘッダとIPヘッダ分を差引いたサイズになります。 例: 1500 - 20 - 20 - 1500とは? = イーサネットのペイロードサイズ=1500バイト(IP,TCPヘッダ含)のことです。 なお、一般家庭などのB-FletsはPPPoEなので1500より小さくなります(詳細は略) </small> --- class: col-2,compact # TCPヘッダ <small> | 図中の表現 | 内容 | 長さ | |----------------------------|--------------------|------| | source port | 送信元のポート番号 | 16 | | destination port | 送信先のポート番号 | 16 | | **sequence number** | シークエンス番号 | 32 | | **acknowledgement number** | アクノリッジ番号 | 32 | | data offset | ヘッダの長さ | 4 | | reserved | 予約(未使用) | 6 | | **control bits** | 制御命令/状態 | 6 | | **window** | 流量制御 | 16 | | checksum | チェックサム | 16 | | urgent pointer | 緊急ポインタ | 16 | </small> ![height400px](images/tcp-header.png) <div class=footnote> <small><small> (脚注1)ヘッダ構造は覚えなくてOK <br> (脚注2)予約の3ビット分はECNへ;RFC3168(2001) </small></small> </div> --- class: img-right,compact # TCPヘッダ <div class=footnote> <small><small> (脚注) ヘッダ構造は覚えなくてOK; ヘッダにポート番号がありますよね?そこだけ覚えておいて欲しいですね </small></small> </div> ![height400px](images/tcp-header.png) - 信頼性、フローコントロール、多重化のための情報がヘッダにあります - **ポート番号はありますが、IPアドレスは無い**ことに注意してください - トランスポート層(TCP)の担当は**アプリケーションの区別(誰?)**です - TCPヘッダにあるのは、ポート番号とTCPを制御する情報 - インターネット層がIPアドレス(住所)を扱うので、 IPヘッダにIPアドレスが書いてあります <br> <small> **TCPとIPはコンビで動作することを忘れずに!** </small> --- class: img-right,compact # TCPヘッダとTCPの動作 <div class=footnote> <small><small> (脚注) 詳細は(中間試験範囲外になる)TCP編の最後のあたりで解説しています。 このあたりのTCPヘッダ詳細は、すでに応用情報処理試験の範囲すら越えていますが、 ネットワークの授業としてはビギナー編です。 プロのエンジニアを目指す人にとってTCPの基本動作は必須要件なので各自で勉強してください (TCPの動作がわからないと基本的な障害対応すらできない)。 IPAの試験群がソフトウエアに偏重してるだけなので、 TCPなんて分からなくてOKなどと勘違いしないようにしてください </small></small> </div> - TCPは、まずコネクションを確立するところから始まります。 仮想通信路の生成もしくはコネクションの初期化とも言えます。 - この初期化が**3-way ハンドシェイク**と呼ばれる有名な手法です。 TCPヘッダの Control bits で命令(**SYN** = シンクロナイズ命令)を送り、 sequence number と acknowledge number をモニタして、 サーバとクライアントが互いに確認(**ACK**, acknowledge が確認という意味)を取りながら行います (詳細は[こちら](/slides/network/tcpip/tpt_tcp/#tcp-details)以降を参照) <div class=digest-end-01></div> --- name: tcp-details class: title, smokescreen, shelf, no-footer # TCP (Transmission Control Protocol) <br> より細かな動作 <div class=footnote> <small><small> 中間試験には出ません。 応用情報処理試験でも出題されないレベルですが、 ネットワークエンジニアとしては基本事項なので、 プロになるなら分かっておいてほしい基本レベルです </small></small> </div> --- class: img-right,compact # TCP: 状態遷移図 <div class=footnote> <small><small> (脚注) 日本の業界人はESTAB を「えすたぶ」と発音しています。外人に通じるのかは不明ですけど </small></small> </div> ![height480px](images/tcp-states.png) - 状態遷移(state transition) - TCPの状態が移り変わっていく様子 - CLOSEDから始まり、いくつかの状態を経て再びCLOSEDになります - 一番上のCLOSEDと右下のCLOSEDは同じものです (図は、右下と上がつながっていると読んでほしいのです) - ESTABLISHED状態が実際のデータ転送を行っている一番大事な状態にあたります - 長くて言いにくいので業界人は、この状態をESTABなどと省略します - 「ACKビットが1」の状態がESTABです(「ACKが立っている」とも言います,後述) --- class: col-2,compact # TCP: コントロールビット - TCPヘッダのコントロールビット部(control bits) - 命令および現在の状態を伝えるもの - 1bitずつ違う意味になっています - 本来このように1bitで十分なので、 (debugしやすい)アプリケーションプロトコル群が冗長なのですね <wbr> | 0 | 1 | 2 | 3 | 4 | 5 | |-----|-----|-----|-----|-----|-----| | U | A | P | R | S | F | | URG | ACK | PSH | RST | SYN | FIN | <div class=footnote> <small><small> (脚注)ECN(予約の3ビット分;RFC3168(2001))は含めていないoriginalコントロールビット </small></small> </div> --- class: img-right,compact # TCP: 通信路の確立 1 ![](images/tcp-init.png) - 3-way handshake - 有名な3-way handshakeです - (論理的な)**仮想通信路**を確立します - この通信路を**コネクション**と呼んでいます。 そしてTCPは**コネクション指向**と言われています。 - コントロールビット**SYN**が確立のお願いで、 **ACK**が了解したという意味です - これを双方向に行い、 双方がACKを返せれば**ESTABLISHED**状態になり、 データ転送が行えるようになります - サーバとクライアント双方で、 それぞれのシークエンス番号(図中ではSEQ番号)を管理しています。 これは送ったデータのバイト数分増加する数字です --- class: img-right,compact # TCP: 通信路の確立 2 ![](images/tcp-init.png) 1. クライアント(C)からサーバ(S)へ - コントロールビットの**SYN**部分を1 - **SEQ番号J**でサーバへ送信します。ACK番号は未定なので通常0 1. サーバが返事を返します - Cのお願いに了解の意味で**ACK**を1 - **ACK番号**にJ+1を設定 - SからCへのお願いの意味で**SYN**を1 - **SEQ番号**にSの番号Kを設定 1. クライアントが返事を返します - SからCへのSYNに了解で**ACK**を1 - **SEQ番号**にCの番号J+1を設定 - **ACK番号**にK+1を設定 <div class=footnote> <small><small> 脚注:1に設定することを「ビットを立てる」と表現します。 <br> 3-way handshakeではデータ転送をしませんがACKを返すときにSEQ/ACK番号を+1します </small></small> </div> --- class: img-right,compact # TCP: 転送 ![](images/tcp-transfer-normal.png) - 右図はHTTPを例にしています - クライアント(C)からサーバ(S)へ`GET / HTTP/1.0`を送信します。 ここではペイロード(データ)サイズが**16バイト**と想定 - C、Sそれぞれで送ったデータ量分SEQ番号は増えます。 変化後の値は**相手から受領確認で返ってくるACK番号と一致**するはずです - C側の**SEQ番号**は**(J+1)に+16**されます (Sが無事に受け取ったら**J+1+16**の**ACK**を返してくるはず) - SはCからの16バイトを受信したので**ACK番号**に**J+1+16**を設定し、 SEQ番号にはSからCに送る400バイトを加算した**K+1+400**を設定 --- class: img-right,compact # TCP: 転送(損傷、紛失、重複、順序の乱れ) ![](images/tcp-transfer-failure.png) - SEQ番号から自分がどこまで送信したか?は分かり、 返信パケットのACK番号を見れば、相手がどこまで受け取っているのか?が分かります - SEQ/ACK番号の抜けや重複、順序の乱れを見ることで、それらの訂正が出来ます - 届いていないパケットがあれば、 一定時間後にTCPが決断して再送もしくは相手に再送依頼などします - TCPがバッファリングし、正しい順序に再構成後アプリケーションに渡します --- class: img-right,compact # TCP: 転送(転送速度の向上)とフローコントロール ![](images/tcp-transfer-accel.png) - 一回毎に確認を待つのは非効率 - 1往復どれくらいか?というと、 北海道〜東京で往復50msくらいかかるので1秒で20往復しか出来ません。 これでは転送速度が30KB/秒くらい... - 確認を待たずに次々と送信しましょう - 確認を待たずに送れるサイズがTCPヘッダのwindowサイズ - そうそうエラーにはならずに次々とACKが返ってくると期待してますよ - フローコントロールの基本 - ヘッダのwindowでネゴしていきます - ホストが忙しいので少し待ってほしいならwindowは小さくしてほしい - 余裕が出来たらwindowを少し大きく --- class: title, smokescreen, shelf, no-footer # TCP/IP周辺の出来事史 <div class=footnote> <small><small> 中間試験には出ません </small></small> </div> --- class: compact # TCP/IP周辺の出来事史 <small> | 年代 | 出来事 | 備考 | |------------|--------------------------------------|-------------------------------------------------| | 1950年代 | タイムシェアリングシステム(OS)研究 | 軍はCICもしくは防空センターの高度化に興味? | | 1951? | SAGE(半自動防空管制)開発開始 | MITリンカーン研究所(1951)、運用開始は1958 | | 1957 | スプートニク1号打ち上げ | 宇宙開発競争のはじまり、空から核ミサイル? | | 1958 | ARPAとNASAの誕生 | 宇宙開発の主導権はNASA | | 1960年代 | ARPAのIPTO部主導でARPANET開発 | IPTOの予算はARPA全体の0.5%(期待されてない?) | | | (ARPANETは60年代後半みたい?) | IPTO部長は対話的コンピューティング関係者 | | 1969/10/29 | ARPANETで最初のパケットが流れる | プロトコルはNCP, UCLA〜SRI間 | | 1970年代 | TCP/IPの設計と開発 | (ARPAと無関係ながら)OSではUnixがブレイク | | 1970年代末 | NCPからTCPへの移行を計画 | UCBがBSD UnixにTCPを実装する案件を受注 | | 1981-1983 | 4.2BSDでのTCP/IP実装 | Bill Joy(pascal,vi,termcap,のちのSUN CTO) | | 1983/01/01 | ARPANETがNCPからTCP/IPへ完全に移行 | 商用化とか対OSI(政治)とかいろいろあるみたい? | | 1991 | HPC Act (by Al Gore) | のちのクリントン政権での情報ハイウエイ構想 | | | | 商用インターネットの躍進がはじまる | | 1995 | Win95登場 | 一般人のインターネット率が急上昇していく | </small>