【TCP】コネクションの確立までの道のり


#レイヤ４の役割
レイヤ4トランスポート層では **パケットを送信元から宛先までのデータ転送を制御・調整する層** となっており、主にTCPやUDPが使用される。TCPに於いては、 **信頼性の高い通信サービスを保証している。** 信頼性の高い通信サービスを確立することによって、転送中のデータがメディアの干渉によって信号がおかしくなり、レイヤ2（データリンク層）のエラーチェックで引っかかるなどが起こってしまうのを防いでくれる。レイヤ２では、同一LAN内の、ノードとノードとの接続で、レイヤ３はネットワークとネットワークの接続だったが、今回のレイヤ４ではホストの、どの通信アプリケーションへのデータかを見分けるためにポート番号によって見分け接続する層。つまり、データの発生元と受け取り元のアプリケーションが対象で、端と端の接続なので **「エンドツーエンド」** の接続を確実にできるようにしている層言える。

　具体的には、TCPヘッダ内にある制御ビットの種類であるACK・SYN・FINなどの確認応答を使用した「受信準備はOKですか？」「準備OKです」といった **送信元と宛先間の通信確認作業(3Way-Handshake)** や、処理能力を上回った情報を送られた場合、転送を一時中止してもらうする **フロー処理** 、また処理しきれずに溢れた場合に転送スピードを下げてもらう **スロースタートアルゴリズムによる輻輳処理** などによって信頼性の高い通信サービスを提供するレイヤーとなる。
　
　これから、この中の送信元と宛先間の通信確認作業である3Way-Handshakeの手順を記述していく。
#コネクションの確立
TCPでは前述のように信頼性の高い通信を提供するためのエンドツーエンドの通信が可能な状態かを確認している。
　
　この確認する方法として **3Way-Handshake** と呼ばれる方法を使用する。名前の通り以下の3つの要求と許可の確認をし、通信できる状態を作り出している。
　
1．送信元が通信路を確保するため、相手にデータ転送の許可要求を出す。（SYN）
2．宛先側が許可を送信元に知らせると同時に受信側も許可要求を出す。（ACK + SYN）
3.最初にSYNを送った送信元も宛先側に許可を出す。（ACK）



以上の手順で送信元と宛先側の双方が許可依頼、許可受領を済ますとコンピュータ上ではESTABLISHEDという状態になる。この状態をコネクションの確立と呼ぶ。
（状態の名称は **netstatコマンド** を使用した時に確認することができる。）

コネクションの確立が終了すると、セグメントの送信が始まる。

![3wayhandshake.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/130302/f38a7032-40fe-b7b9-35eb-ff3d9bfcb9ab.jpeg "3wayhandshake.001.jpeg")


#コネクションの切断
TCPではコネクションを確立させるために上記の3Way-Handshakeを行い、双方の許可申請＆受諾によって正確な通信経路を確保するが、データ送信後の切断する際にも **双方からの終了申請＆受諾によって切断を確実なものにする。** 

手順は以下の様になる。

1．送信元が切断要求を送る。（FIN）
2．宛先側が切断許可を出す。（ACK）
3．宛先側が切断要求を送る。（FIN）
4．送信元が切断許可を出す。（ACK）

これで両ノードが元のCLOSED状態になり、切断終了となる。

![3wayhandshake.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/130302/9c980dc3-a550-cabd-ce33-686e9d8f4ff6.jpeg "3wayhandshake.001.jpeg")

#実際の挙動
##tcpdumpとは
tcpdumpコマンドは通信時にどのデータが送られているかを確認することができるパケットキャプチャのためのツールです。

一般的に「パケットキャプチャ」のワードで検索すると出て来るWireSharkというアプリも同様にパケットキャプチャをすることが出来ます。WireSharkではtcpdumpコマンドでは出力されない細かな情報も表示してくれるのでとても便利がいいのですが、tcpdumpはCUI操作での基本的なコマンドの一つなので今回は、tcpdumpを使用します。

##使ってみる
###コネクションの確立
単純にターミナル上でtcpdumpコマンドを使用するとすべての通信をキャプチャしてしまい、大変なことになるので、tcpdumpコマンドに対して、ホストとポート番号の指定をし、制限しておきます。

今回、ホストには 「www.example.com」 を指定し、port番号は 「80」 を指定したいと思います。
ではやっていきましょう。
まず、以下のコマンドを打ってください。

```html:ターミナル
$ sudo tcpdump host www.example.com and port 80
```

このあとパスワードの入力指示が出てきた場合はパスワードを入力します。
その後、ブラウザ上でwww.example.comへアクセスすると同時に以下に表示され、パケットをキャプチャ出来ます。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/130302/55949364-b6ac-41bc-a34f-be6b845802fa.png)



以上の画像のように囲んでいる部分のキャプチャが３Way-Handshakeの部分です。
この表示だと１行目が「SYN」、２行目が「ACK+SYN」、３行目が「ACK」となっています。
この３行によりコネクションの確立がされたことが伺えます。

ただ、どの部分が何を意味しているのかわからないので、それぞれの意味を左から説明していきます。


![2.png](https://qiita-image-store.s3.amazonaws.com/0/130302/6574ff7e-33e2-f68f-ef6e-23e46d6aa768.png)


|番号|名称|解説|
|:--|:--|:--|
|①|時間|キャプチャ時間|
|②|送信元IPアドレス|パケットの送信元|
|③|宛先IPアドレス|パケットの宛先|
|④|フラグ|SYN→「S」, ACK→「.」, FIN→「F」 |
|⑤|シークエンス番号|パケットを分割した際の各データ番号|
|⑥|ウィンドウサイズ|バッファのサイズ|

このような意味になっています。

###コネクションの切断
次はコネクションの切断です。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/130302/d1999a1d-9a86-5e14-616f-1d0bd6a79ff3.png)


以上の画像にあるようにお互いのノードがFINを出し合いコネクションを切断しているのが、見て取れます。


## 参考文献

- [IBM Redbooks その他](http://www.redbooks.ibm.com/jp/support/redbooks/etc.html) の [TCP/IP チュートリアルおよび技術解説書 GG88-4005-00](http://publibfp.dhe.ibm.com/epubs/pdf/g8840050.pdf)

- [3分間ネットワーキング](http://www5e.biglobe.ne.jp/aji/3min/)

- [TCPDUMPの出力を見てみよう](https://net-newbie.com/tcpip/tcp/tcpdump.html)