TCP/IP Protocol-Suite


#はじめに
本記事では、[前回の記事](https://qiita.com/DAISUKE15/items/22012342561078cb25f3)におけるTCP/IPの深掘りをしていこうと思います。
先に申し上げておきますが、今回は結構ボリューミーな内容になっております。
目次を参照しつつ、ご自身で気になるところだけ見て頂ければと思います。

表題のProtocol-Suiteとは、複数のプロトコルをひとまとめにしたもの、プロトコル全体といった意味合いです。
Protocol-Stuckと同じ意味で使われる場合が多いようですが、厳密には意味が違うらしいので気になる方は調べてみてください。


#TCP/IPってなんだっけ？
一言で言ってしまえば、
**インターネットでデファクトスタンダード的に利用されているNW技術**。
IETF(Internet Engineering Task Force)で技術の標準化が行われており、ほとんどのコンピュータやNW装置においてTCP/IPが実装されています。TCP/IPでは、以下のような階層構造で技術を分割しているという話を前回の記事でご紹介しました。

|Layer|代表的なプロトコル|
|--|---|
|アプリケーション層  |HTTP/FTP/SMTP/POP3/DNS/Telnet...|
|トランスポート層    |TCP/UDP|
|インターネット層    |IP/ICMP/ARP|
|NWインタフェース層  |Ethernet/PPP...|

#カプセル化/非カプセル化

各レイヤの役割を見る前に、実際のコンピュータ同士が通信を行う際にどのような処理が行われていくかを先にご紹介します。

![encapsulation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507113/26bf912c-5cb5-d6de-4fb7-779bc0dfb591.png)

<dl>
  <dt>送信フェーズ</dt>
  <dd>1. 送信側のコンピュータ上で、アプリケーションが宛先に送る<strong>データ</strong>を作成</dd>
  <dd>2. 上位層から受け取ったデータに、その層で使用する<strong>ヘッダ</strong>(制御情報)を付与</dd>
  <dd>3. ヘッダ＋上位層データを以降の下位層へ渡す</dd>
  <dt>受信フェーズ</dt>
  <dd>1. 下位層からデータを受け取る</dd>
  <dd>2. その層で使用するヘッダを読み取る</dd>
  <dd>3. <strong>ヘッダを取り除き</strong>、上位層へデータを送る</dd>
</dl>

新しくヘッダという単語が出てきましたが、これは後ほど説明します。受け取ったデータの先頭になんかくっつけるものと覚えておいてください。
このようにヘッダで何重にも包み込んでいく様子から、送信時の処理のことを**カプセル化**(encapsulation)と呼びます。
逆にヘッダを除いていく受信時の処理を**非カプセル化**(de-capsulation)と呼びます。

このときの処理で各層が扱うデータ単位を**PDU**(Protocol Data Unit)と言います。
PDUの構成としては基本的に「ヘッダ情報＋上位層データ」であり、以下のように呼ばれています。

|Layer|PDU|
|--|--|
|トランスポート層    |**TCPセグメント** or **UDPデータグラム**|
|インターネット層    |**パケット**(packet)|
|NWインタフェース層  |**フレーム**(flame)|


<br>
では実際に各レイヤの役割を見ていきましょう。
上位層から見ていった方がイメージが湧きやすいので、まずはアプリケーション層から。

#アプリケーション層
- **通信アプリケーション毎のデータの取り扱い方法や、通信の流れを定義する。**

そもそも通信アプリケーションってなんだって話ですが、例えばメーラー(Gmail/Thunderbird等)や、Webブラウザ(Google Chrome/Mozilla Firefox/MS Edge等)なんかが当てはまります。インターネット上には様々な通信サービスが存在していますが、情報発信や交換のための各種サーバーがあり、クライアントとサーバー間で情報伝達を行っています。

##FQDN

では、「このWebサイトにアクセスしたい」「友達とメールのやりとりをしたい」となったとき、どうやってその相手にアクセスするのでしょう。私たちは普段当たり前のように、ブラウザを立ち上げてクエリを叩いて検索したり、メーラーを立ち上げてメールを送っていますが、どのような仕組みでこれらが実現されているのか？

通信サービスを利用するとき、その通信相手を決定するために**アドレス**と呼ばれる識別子を指定します。
インターネット上の通信相手は、**FQDN**(Fully Qualified Domain Name)と呼ばれる**文字列**形式で識別可能です。

![domain_name.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507113/90fd2a86-5b87-5ca0-56d1-0a5b402a66f0.png)

各通信サービスではこのFQDNを用いて宛先を指定します。
図のようなネットワーク「piyo.co.jp」内の、WWWで使用されるアドレスは`http://www.piyo.co.jp`、Mailで使用されるアドレスは`tmp@piyo.co.jp`と表現されます。
私たち人間にとって、文字列が使えることによって意味付けがしやすい、覚えやすいなどといったメリットがあります。

インターネットでは、NWを国別、組織別、会社別などの階層構造に分割して管理しており、この管理単位を**ドメイン**と呼んでいます。
ドメインはツリー構造で管理され、頂点から**ルートドメイン**(.)、**トップレベルドメイン**(net/com/jpなど)、**セカンドレベルドメイン**(co/ac/go)と続いていきます。これらのドメインについては深掘りしませんので、気になる方は[JPNICのサイト](https://www.nic.ad.jp/ja/dom/system.html)をご覧になってみて下さい。

##WWW通信
実際のプロトコルを見ていきましょう。
まずはWWW閲覧に使用するプロトコルとして**HTTP**(HyperText Transfer Protocol)があります。
WWWの情報は**HTML**(HyperText Markup Language)で構成されており、HTMLでは[ハイパーリンク](https://wa3.i-3-i.info/word1187.html)や画像、映像を埋め込んだりと効果的な情報表示が可能です。

HTTP通信の流れ自体は以下のようになります。
1. ユーザがブラウザにURLを入力
2. クライアントはURLに記載されているサーバに情報を要求
3. サーバは要求された情報(HTMLファイル)をクライアントに送信
4. クライアントはそのHTMLファイルを解析
5. HTML内に、埋め込まれたデータ(ハイパーリンク/画像など)があれば2.へ
6. 無ければ終了

※最近は通信内容を暗号化可能な**HTTPS**(HTTP Secure)が利用されることが多い


##E-mail通信
一般的なメールの送信を行う場合は**SMTP**(Simple Mail Transfer Protocol)、受信時は**POP3**(Post Office Protocol ver.3)または**IMAP4**(Internet Message Access Protocol 4)のプロトコルを用います。

- 電子メール送信時の流れ(**SMTP**)
<dl>
  <dt>1. メールの送信</dt>
  <dd>相手のメールアドレスを指定し、メールを送信。このときメールは自ドメインのMailサーバに一度格納される</dd>
  <dt>2. メールの宛先解析</dt>
  <dd>自ドメインのMailサーバは、宛先ドメインのMailサーバを調べる</dd>
  <dt>3. Mailサーバによる宛先ドメインへの配送</dt>
  <dd>自ドメイン内のMailサーバは、宛先ドメインのMailサーバへメールを送信する</dd>
  <dd>※宛先が自ドメイン内であれば、Mailサーバ内の宛先ユーザのメールボックスに格納する</dd>
  <dt>4. メールの受け取り・保管</dt>
  <dd>メールを受信したMailサーバは、該当ユーザのメールボックスにメールを保管</dd>
</dl>
- 電子メール受信時の流れ(**POP3** or **IMAP4**)
<dl>
  <dt>メールの受信</dt>
  <dd>1. 受信したユーザは、Mailサーバのメールボックスにメールが届いてるかを確認</dd>
  <dd>2. メールが届いている場合、自身のコンピュータに転送し、受信する</dd>
  <dd>※POP3ではメールを受信するとサーバーから該当のメールは削除され、その後はユーザのコンピュータで情報を管理します。しかし、IMAP4では受信してもサーバーからは削除されず、Mailサーバ上で情報を管理することになります。</dd>
</dl>

##Telnet, SSH
最後に管理系プロトコルとして**Telnet**、**SSH**(Secure SHell)をご紹介します。
どちらもNW経由で他のコンピュータやサーバーに接続し、遠隔操作を行うためのプロトコルです。

では違いは何かというと、通信内容が暗号化されるかされないかの違いで、

Telnetは通信内容が暗号化されない、SSHは暗号化される。

といった感じです。現在はSSHを使うのが主流のようです(安全ですからね)。

##アプリケーション層のプロトコルまとめ
今まで出てきたプロトコルに加えて、他にもこんなのあるよ～ってプロトコルをご紹介します。

|プロトコル|役割|
|--|--|
|**FTP** <br>(File Transfer Protocol)  |クライアントとサーバー間のファイル転送用プロトコル|
|**DNS** <br>(Domain Name System)  |URLやメールアドレスのドメイン名とIPアドレスとの対応付けを管理する|
|**SNMP** <br>(Simple Network Management Protocol) |NW管理・制御のためのプロトコル|

#トランスポート層
- **コンピュータ内のアプリケーション通信を制御**

コンピュータ内部では複数のアプリケーションが動作しています。
例えばブラウザを立ち上げたまま、メーラーでメールをチェックしたり、Youtube見たり、、、
かくいう私もこういったことを頻繁にしていますが、もしブラウザのデータとメールのデータがごちゃごちゃになって手元に来たら、アプリケーションとして全く役に立ちませんよね。

このような事態を防ぐために、トランスポート層ではアプリケーション間の通信路を形成し、データが混ざらないようにしてくれています。

早速ですが、トランスポート層にはプロトコルとして**TCP**(Transmission Control Protocol)と**UDP**(User Datagram Protocol)があります。いずれもアプリケーション間の通信路を決定するという機能を実装していますが、両者には大きな違いがあります。

TCPは信頼性のある通信を提供しますが、UDPには信頼性がありません。

こう書いてしまうとUDPの聞こえは悪いですが、音声やビデオのストリーミング再生ではこのUDPが使われています。

どうして？？
他にもTCP/UDPの違いはありますが、その前にポート番号と呼ばれるアプリケーションを識別する番号についてご紹介します。

##ポート番号
先述の通り、1台の端末には複数のアプリケーションが存在し、同時に通信が可能となっています。
それらがごちゃ混ぜにならないように、上位層のアプリケーションを識別するための番号が必要となってきます。それが**ポート番号**です。

ポート番号は0～65535の数値で表現され、サーバー用とクライアント用で大きく2つに分けられます。

<dl>
  <dt>ウェルノウンポート番号(サーバー用ポート番号)→範囲：0～1023</dt>
  <dd>サーバーで稼働しているアプリケーションプロトコルを動的に識別。</dd>
  <dd>代表的なプロトコルに対するポート番号は国際的に決められている。例えばHTTP:80番、SMTP:25番など</dd>
  <dd>クライアントから、サーバー上のどのアプリケーションへ通信を行いたいかを指定できる。</dd>
  <dt>クライアント用ポート番号→範囲：1024～65535</dt>
  <dd>クライアントで稼働しているアプリケーションプロトコルを識別。</dd>
  <dd>プロトコルが起動したタイミングで重複しない値がランダムに割り当てられる。</dd>
</dl>

##TCP(Transmission Control Protocol)
TCPは**信頼性のある通信を保証**します。
信頼性を保つために以下のような仕組みが実装されています。

<dl>
  <dt>コネクション管理(3way-handshake)</dt>
  <dd>コネクションとは、アプリケーション間で確立する通信路のこと。</dd>
  <dd>コネクションを確立することで信頼性のある通信を実現できる。</dd>
  <dd>コネクションを使用してデータの送受信を行い、データの送受信が終わったらコネクションを切断する。</dd>
  <dt>応答確認</dt>
  <dd>全ての送信データが宛先に到達しているかの確認。</dd>
  <dd>宛先側は、データを受信すると送信元側に応答を返信する。</dd>
  <dt>シーケンス管理</dt>
  <dd>データ送受信が成功しているか確認するために、データに番号を付与。</dd>
  <dd>上記の応答確認の際に、何番目までのデータを受信したかを示す情報を付与する。</dd>
  <dt>フロー制御</dt>
  <dd>データ転送スピードを調整。適切なタイミングでデータを転送する。</dd>
  <dd></dd>
</dl>

![syn_ack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507113/fb28ca76-a641-afd1-5398-68d1a4e000e0.png)


##UDP(User Datagram Protocol)
UDPはTCPとは異なり、コネクションを確立しません。そのため**通信に信頼性はありません**。
送信者側は相手にデータが届いたかも分かりません。UDPは一定間隔で相手側にひたすらデータを送り続けます。
どういった場面でこのプロトコルは使われるんでしょう？

先ほど答えを書いてしまいましたが、**速度重視**のアプリケーションでUDPは力を発揮します。

音声や動画などのリアルタイム性が重視されるアプリケーション、例えばZoomなんかではこのUDPが使われてます。
UDPでは細かい制御がなされない分、装置やNWに負荷をかけない効率の良い通信が可能となっています。


#インターネット層

- **end-to-endの通信を実現**
- **IPアドレスを使って通信相手を特定**

インターネット層の役割は、NW上の端末間でパケットの送受信を可能にすることです。(パケットはインターネット層でのPDUでしたね)

この層で一番大事なのは、**IPアドレス**に他なりません。

IPアドレスは「通信相手を識別するための住所」と例えられます。


**IP**(Internet Protocol)はパケットを届ける際に、このIPアドレスを用います。
IPアドレスはIPネットワーク上の全ての端末に割り当てられており、これによって目的の通信相手にパケットを届けることができます。

IPアドレスについては、
アドレス形式、アドレスクラス、サブネット分割、IPアドレッシング、ARP、ICMP、NAT、、
など重要なワードがたくさんあります。
しかしここで全て説明してしまうと、全体の流れが見えにくくなってしまいます。
ただここら辺の話はめちゃめちゃ大事なので、後日IPアドレスについての記事を書こうと思います。

とりあえずこの層では、IPアドレスっていう「端末の住所」を特定して、相手にデータ(パケット)を送るんだ～くらいの感覚で覚えておいて下さい。

##ルーター
インターネット層では、IPアドレスを用いて送信元から宛先までの経路決定を行います。
この経路決定(ルーティング)を行うデバイスを**ルーター**と呼びます。
(※正確には「パスの決定(ルーティング)」＋「パケット転送(フォワーディング)」を行うのがルータ)

ルーティングを行うためには、**ルーティングテーブル**という「宛先NW」と「宛先NWに到達するための次のルーター(Next Hop：**ネクストホップ**)」を登録したテーブル(リスト)が必要です。

ルーターはこのルーティングテーブルを持っており、かつルーター自身の**各ポート**はそれぞれIPアドレスを持っています。

少しややこしくなってきましたね。
整理すると、これから送信されるデータはルーティングテーブルの内容を見て、書いてある情報に従い次のルータへ、次のルータへ、、とどんどん転送されていきます。誤ったネクストホップが登録されていたり、そもそも宛先NWが登録されていないなんてことが無いように、正確にルーティングテーブルを作成しなければなりません。

ではどうやって作成するのでしょうか？大きく二つの方法があります。

<dl>
  <dt>スタティックルーティング</dt>
  <dd>管理者が手動で経路を設定し、ルータに学習させる。</dd>
  <dd>ルーターの経路更新負荷が少なく、処理が安定する。</dd>
  <dd>大規模NWには向かない→小規模NW向け</dd>
  <dt>ダイナミックルーティング</dt>
  <dd><strong>ルーティングプロトコル</strong>を設定し、ルーター同士が自動で経路を学習する。</dd>
  <dd>管理者の設定作業にかかる負荷を軽減できる。</dd>
</dl>

明示的に登録されていないNWへの経路を定義するものとして**デフォルトルート**がありますが、これも後日の記事でまとめます。

#NWインタフェース層

- **通信用ハードウェア間でデータを受け渡す**。

通信用ハードウェアにはLANやWANで採用される様々な規格があります。
今回は、現在最も主流で使用されているEthernetについて見ていきましょう。

##Ethernet
**Ethernet**はLANで最も使用されているNW製品の規格であり、伝送路の規格や制御ルールを定めています。
Ethernetでは、伝送路上の通信用ハードウェアを識別するために**MACアドレス**を使用します。

またまたアドレスなるものが出てきました。
IPアドレスを「住所」と例えるなら、MAC(Media Access Control)アドレスは「その人個人の名前」でしょうか。

誰かに郵便物を届ける時、その人の名前だけ分かっていても送ることは出来ません。
住所で相手の場所を特定することで、確実に届くわけです。

つまりIPアドレス(住所)とMACアドレス(名前)は、データを送るときに絶対必要だよねって話です。

少し脱線しましたが、MACアドレスについて少し詳しく見ていきましょう。
MACアドレスは伝送路の始点or終点となるNWアダプタ(NIC:Network Interface Card)に設定されるものです。

MACアドレスアドレス自体は48bitで構成されており、前半24bitが**ベンダーコード**、後半24bitが固有のアドレスです。
ベンダーコードってなんやって話ですが、例えばPCを製造してるメーカーさんなんかが発行してる番号です。
後半24bitはベンダーが個別に管理している部分で、重複のない固有のアドレスになってます。基本的にNIC出荷時に付加されて、変更できません。

じゃあ通信にMACアドレスが必要なら、どうやって通信相手のMACアドレス特定するの？IPアドレスは？


その話は**ARP**だったり**DNS**で解決できます。これは次回の記事で詳しく解説します、、

Ethernetの規格なんかも、その他のネットワーキングデバイスと同じ記事にまとめようと思います。

誤字・修正等ありましたらコメントお願いします。