(基本情報技術者試験対策) TCP: 通信の信頼性を確保するプロトコル

## Transmission Control Protocol(TCP)

TCPはトランスポート層のプロトコルで､セッションの管理を行い通信の信頼性と効率性を向上させる役目を持つ｡
しかし､信頼性を担保するための機構が複雑で関連する情報を格納するTCPヘッダの容量が大きいこともありコネクションの確立を何度も繰り返すような通信では非効率になりやすい｡
TCPはコネクション型通信に分類され通信相手と確実に通信ができるようにコネションを確立します｡コネクションは特定のコンピュータとの間に確立するので､ユニキャスト通信しか行なえません｡

## コネクションの管理

TCPは下図のような状態遷移をする

![tcp_state_transition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185247/afb7769c-21fb-09e5-b8f7-daa10c10ff6a.png)


### 1 セッション確立

**アクティブオープン**
CLOSED状態の送信側がSYNのビットの立ったメッセージを送信しSYN-SENT状態に遷移｡
受信側からSYNとACKのビットの立ったメッセージを受け取り､応答確認用にACKの立ったメッセージを送信しESTABLISHEDへ遷移｡
**パッシブオープン**
CLOSED状態からLISTEN状態へ遷移｡
SYNの立ったメッセージ(接続確立要求)を受け取り､SYNとACKの立ったメッセージを受信側に送信する｡その後SYN-RCVD状態へ遷移｡
受信側からACKの立ったメッセージを受け取りESTABLISHED状態へ遷移｡

![tcp_session_establishment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185247/41e46c98-2542-af2b-297a-1043d30142c6.png)

コネクション確立までに最低3回のやり取りが必要になるのでこの処理を3wayハンドシェイクと呼ぶ｡

### 2 セッション終了

**アクティブクローズ**
パターン1
FINの立ったメッセージを送信し､FIN-WAIT1へ遷移
送信したFINに対する応答確認ACKを受信しFIN-WAIT2へ遷移
受信側からFINを受信し､ACKの立ったメッセージを送信しTIME-WAITへ遷移
ACKが受信側に確実に届くまで待機しCLOSEDへ遷移

パターン2
FINの立ったメッセージを送信し､FIN-WAIT1へ遷移
受信側からもFINが送信された場合これに対する応答確認ACKの立ったメッセージを送信しCLOSINGへ遷移
最初に送信したFINに対する応答確認ACKを受信し､TIME-WAITへ遷移
待機時間が終了したらCLOSEDへ遷移

**パッシブクローズ**
送信側からFINの立ったメッセージを受信し､応答確認のためにACKの立ったメッセージを送信､その後CLOSE-WAITへ遷移
FINを送信し､LAST-ACKへ遷移
FINに対するACKを受信したらCLOSEDへ遷移

![tcp_session_close.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185247/6d30ad76-aa9b-d615-3a33-8903dd04fa05.png)


## TCPセグメント

![tcp_header.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185247/0f962b03-0180-73af-ab51-f7fc20e3aba5.png)


1行分のデータ長は32bitで5行分のヘッダ情報は固定なのでTCPヘッダは最低20byteの大きさになる｡
オプションとデータは合わせて最大10行分(40byte)書くことができる｡

### TCPヘッダの用語

URG(urgent)
: 緊急に処理すべきデータが含まれていることを示す

ACK(acknowledgement)
: 確認応答番号のフィールドが有効であることを示す

RST(reset)
: コネクションの強制切断を示す｡何らかの以上が発生したときに送信される｡

SYN(synchronize)
: コネクションの確立要求を示す

FIN
: コネクションの正常な終了を要求することを示す

順序番号
: 送ったデータの順序を表す｡受信した確認応答番号の値と同じ

確認応答番号
: 確認応答番号の値｡受信した順序番号+データサイズ

チェックサム
: TCPヘッダとデータ部のエラーチェックに使う値

緊急ポインタ
: URG=1のときに使用される｡緊急データの開始位置を示す｡

## 信頼性を確保するための機能

### 再送制御

データを送信している途中でエラーが起こり一部のセグメントが届かないことがあります｡
通常データの送信がうまくいったら受信側からACKビットの立ったメッセージが送信されますが､正しく届かなかった場合､ACKメッセージが返ってこないことになるのでその時にそのセグメントを再送します｡

### ウィンドウ制御

TCP通信ではセグメントを送る｡ACKメッセージを受け取る｡次のセグメントを送る｡ACKメッセージを受け取る...というふうにデータのやり取りを行いますが､一回一回確認応答を待っていては効率的な通信はできません｡そこでウィンドウ制御では､ACKの受信を待たずにセグメントをどんどん送信します｡
コネクション確立時に2つのコンピュータはアプリケーション層にデータを送る前に一時的にどのくらいのデータを保持しておけるかをTCPヘッダに記載したウィンドウサイズ(バッファサイズ)という値で互いに知っています｡ウィンドウサイズを超えない範疇ではACKを待たずにデータを連続送信しても構わないのです｡またウィンドウサイズに達したあともACKの受信を待たずにすむように､スライディングウィンドウという技術もあります｡
スライディングウィンドウでは受信側は毎回ACKを送信します｡送信側はACKを受け取るとウィンドウサイズを1つずらします｡ずらすことでACKを待たずに遅れるセグメントを拡張させることができるのでデータを贈り続けることができるのです｡

### フロー制御

多数のクライアントとやり取りを行うサーバはいともたやすくバッファがなくなってしまいます｡そこでサーバはデータを受け取るたびにウィンドウサイズを小さくしていき､残りのウィンドウサイズをクライアントに通知します｡そして余力ができたらウィンドウサイズを広げてそれをクライアントに通知します｡
他方クライアント側ではウィンドウサイズに合わせてデータを送信します｡バッファがなくなれば一旦待機します｡サーバのウィンドウが空き次第再度データを送ります｡

### 順序制御

TCP/IPでは一度に送信できるデータ量の上限(MSS)があったり､受信側のバッファサイズによっても遅れるデータサイズが制限されることがあります｡
そこでTCPではデータをセグメントという単位に分割して送信します｡一つのデータをセグメントに分けて創始すると正しい順番で送信ができないといけません｡そこで順序番号というものを使って制御することを順序制御といいます｡