【読書メモ】「ネットワークはなぜつながるのか」No.2 TCP/IPを理解する

# はじめに
「ネットワークはなぜつながるのか」の読書メモ第２弾です。
今回は２章のTCP/IPについてまとめていきます。

# TCP/IPとは？
OSのプロトコルスタックの中にあるプロトコルの１種
### プロトコルスタック
OSが持つ通信用のソフトウェア群

### TCP
主にWebやメールなどの送受信に使用される。
データが正確に、順序正しく、重複なく目的地に到達することを保証する。
接続の確立や終了等一連の流れを担当する。
TCPとは別にDNSや動画の送受信に使用される「UDP」というものもある。

### IP
データの運搬を担当。TCPから渡されたデータを目的地まで届けるための制御情報の付加、イーサネットのアドレスの特定等を担当する。
エラーの通知等行う「ICMP」　　イーサネットのMAXアドレスを調べる「ARP」という仕組みを持つ。

# データの送受信の流れ
ここではざっくりと概要を書きます。
様々なプロコトルやハードウェアが役割分担して行う
*【クライアント側（送信側）】*
アプリケーション
↓  TCPにデータ送信を依頼
TCP 
↓ 接続するための準備を行う（データを保管するメモリ領域を確保したり、宛先等の制御情報を作成）
IP
↓ TCPから受け取ったデータを目的地まで届けるための制御情報を付加（MACアドレス等)
LANアダプタ(LANドライバも含む)
↓ IPから受け取ったデータを電気、信号に変換して送る

*【サーバー側(受信側)】*
LANアダプタ
↓受け取った電気、信号をデータに変換してIPに渡す
IP
↓受け取ったデータをTCPに渡す
TCP
↓受け取ったデータをアプリケーションに渡す

# TCPの役割
それではTCPの動きが見ていきます。
TCPは
ソケット作成(socket)→接続(connect)→送信(write)→受信(read)→切断(close)
という一連の流れを担います。

### socketとは
データの出入り口のようなものです。
実体は、プロトコルスタックが持つ、制御情報を記録するメモリ領域です。
このメモリ領域には
* 宛先のIPアドレス
* ポート番号
* 動作状態(接続完了、受信待ちなど）
といった情報が逐次記録されていき、プロトコルスタックはこれらを参照しながら動作しています。
socketを作る　＝　　制御情報を１行追加するようなイメージです。
scoketの行はこのようになってます
```
Proto                Local Address   Foreign Address  State                      PID
TCP(プロトコルの種類)    [自身のIPアドレス]  [宛先のIPアドレス]  LISTENING(相手からの接続待ち)  ソケットを利用しているプログラムの識別番号
```
netstatコマンドで参照できます。

### socketを呼び出した際の動き
アプリケーションがsocketを呼び出し ⇨ TCPに送受信の準備依頼が行われる ⇨ ソケット１つ分のメモリ領域を確保　⇨
ステータスに初期状態を表す値をセット　⇨ アプリケーションがどのソケットかを示す(ソケットは複数存在するケースがあるため)ディスクリプタというものを通知する。
こう言った一連の動きが実行されます。
ディスクリプタというものを通知しておくことで以後、アプリケーションが何かを依頼する際ディスクリプタを通知することでプロトコルスタックは、ソケットにある情報を参照できるようになります。

### conect(接続)とは
socketを作成したら次は接続の準備を行います。
その際に使用するのがconectです。
以下のような流れで行います。
プロトコルスタックに相手先のIPアドレスとポート番号を伝える　⇨ 相手側のサーバーに自身の情報を伝え接続許可をもらう　　⇨
送受信の際にデータを一時的に保管する領域（バッファメモリー）を確保する。

### 制御情報とは？
ここで出てきている制御情報とは何なのか説明します。
制御情報には大きく分けて２つあります。
1. クライアントとサーバーがやりとりするための情報(やり取りを行う都度データに付加して送リます、パケットの先頭につけるので「ヘッダー」と呼ばれます)
2. ソケットに記録し、プロトコルスタックの動作を制御するための情報
このうちのヘッダーには、やりとりを行う度に、コントロール・ビットいうフィールドに値を付加します。この中の情報で通信制御上で意味を持つものになります。

https://ja.wikipedia.org/wiki/Transmission_Control_Protocol

よく登場するのが
ACKという値になります。
ACKを1にして返すことで、データが正常に届いたと認識することができます。これにより互いに応答確認を行います。

conect例でいくとconectの一連の動作を行い、相手側からACKのデータが返ってきた際に接続が完了した。ということになります。これをコネクションと呼びます。

### write(送信)とは
接続が完了したら次は送信動作です。
writeでデータを送る際は、一気に送信するのではなく、データをある一定ためてから送信を行います。
イーサネットでは1500バイトになっています。
formからデータを送る場合などデータが大きくなる時は分割して送信を行います。
データのことをパケットと呼ぶのですがパケットの大きさの表現方法は２種類あります。

*MTC* ヘッダーも含めたパケットの長さ
*MSS* ヘッダーをのぞいたパケットの長さ
分割する時は、MSSの範囲で、データを分割して待機します。そしてタイミングが来たらそれぞれの断片にヘッダーを付加して送信を行います。
その際に、分割したデータの順番や繋ぎ目が相手側が認識できるようにシーケンス番号も付加します。
シーケンス番号の初期値は乱数で決定され、届いたデータのMSSで計算して何バイトまで届いたか判別します。それに加えてシーケンス番号に+1したACK番号というものを付加して返却することで送信側に次に送信するバイトのシーケンス番号を知らせます。
例：
1~1461までのデータが送られたとしたらそれに+した1462をACK番号として返却
そうすることで、送信側はそれに続く1462からのデータを送信することができる
これにより互いに何バイト分送信するのか認識することができ、応答がないと送り返すといったことができる。
この動作を　*受信確認* と呼ぶ。

### writeの効率的に送信を行う仕組み
　データ量が多い時など、ACK番号が返ってくるまで送信を待つと非効率になるので、それらを改善する以下のような仕組みが存在する
1. 受信側がデータを受信した際に、送信側にバッファ容量の残量を通知する。
2. 送信側はそれを超えない範囲で送り続ける。
3. TCPがバッファメモリにあるデータをアプリケーションに渡すタイミングでバッファメモリに空きが生まれる。その際に再び、空き容量を伝える。(ウィンドフィールドという項目を通して伝える)この時にACK番号も送る。
4. 再び超えない範囲で送信
これらを繰り返す。この受信可能な最大値をウィンドサイズと呼ぶ。

### close(切断)とは
webの場合、サーバー側が全てのデータを送り返した時にclose呼び出す。close状態になったことを知らせる情報を付加して送信する。
制御情報を受信したら、バッファに置いて相手側にACKを送る。そしてアプリケーション側がバッファに置いてある制御情報（closeを知らせるもの）を取りに来たら、終了を認知するので送信側からもcloseを呼び出し、制御情報をサーバー側に送信する。サーバ側からACKが帰ってきたら終了となる。そうして一定期間たった後ソケットを消して、完全に処理を終える。
ここまでがTCP視点から見た送受信の流れとなる。

#IPとイーサネットの送信動作
TCP/IPはルータとハブの２種類を経由してパケットを運ぶ。
IPがそれらを行う流れは以下の通り
1. TCPがデータの断片にTCPヘッダを付加し「〜っていうAPIへアドレスまで送信してください」とIPに依頼する
2. IPはTCPからデータを一塊と認識(中身のデータは一切見ない)先頭にIPヘッダとMACヘッダを付加する
3. LANアダプタ(ネットワーク用のハードウェア、パソコン内部に組み込まれている)にデータを渡す
4. LANアダプタが電気信号に変換しハブ、ルーターを通して送信

IPヘッダには、宛先だけでなく、送信元のIPアドレスも付加する。
IPアドレスは実際にはLANアダプタに割り当てられており、LANアダプタが複数存在する場合は、どのアダプタから送信するか判別する必要がある。
その際に使用するのがIPの表となる。
IPの表は以下の通り
```
NetWork Destination    Netmask         Geteway                interface                  
[IPアドレス]             255.255.255.0   [中継先ルーターのIPアドレス] [対応するLANアダプタのIPアドレス]
```

このような形式にNetWork Destinationに記載されているIPアドレスの左側が一致する行の
interface(LANアダプタ)を使ってGeteway(中継先のルータのIPアドレス)にパケットを送信するということになる。

IPは中継先のIPアドレスから「ARP」という仕組みを利用してイーサネットのアドレスであるMACアドレスを調べる。
イーサネットにはブロードキャストという仕組みがある。
これは繋がっている全員にパケットを届ける機能。これを利用して、宛先のIPアドレスを持っているかを聞き、所持しているルータのMACアドレスを取得している。その際に、キャッシュに保存することも行うことで、既にキャッシュに存在する場合は調べなくて良いようにしている。これにより実行効率を上げることを実現している。こうしてMACヘッダをセットしパケットが完成するまでをIPが担う。ここまでをIPが担うことでLANアダプタは幅広いデータに対応することができる。
実際には中継先のルータに到着するたびにIPが次のMACアドレスを調べることを繰り返し、目的地まで運搬している。

# まとめ
以上がTCPとIPがデータを運搬するまでの流れになります。
アプリケーション、TCP、IP、LANアダプタ、ハブ、ルーターなどそれぞれが役割を分担することで、幅広いデータ、形式に柔軟に対応する仕組みには驚かされました。
わからない用語だらけで読み進めること、理解に時間はかかっていますが、少しずつ学んでいきたいです。