LoginSignup
10
8

More than 5 years have passed since last update.

TCPのおかげでデータが確実に届く!

Last updated at Posted at 2019-03-09

データってどうやって送信されているの?

私は前の記事で、HTTPに則ってWebブラウザとWebサーバの通信に適したアプリケーションデータ(リクエスト・メッセージ)が作成されることを理解しました。

しかし、実際にそのデータが送信される時の仕組みについては理解できていません。今回は相手にデータを届けるためのプロトコルである、TCPについてまとめていきます。

これは何の記事か?

プログラミングしか学んでこなかったエンジニアが本を参考に、TCPの仕組みについて大まかにまとめた記事です。

対象読者

  • プログラミングしか学んでこなかった
  • TCPってなんですか??

この記事のゴール

  • TCPでのデータ通信の特徴について、大まかに説明ができる。

全体像の把握

この記事は、WebブラウザがWebサーバに対してデータを送信するときの、トランスポート層で行われる処理のうち、TCPについてまとめたものになります。(赤枠の部分)

network-OSI参照モデル (3).png

トランスポート層の役割は?

トランスポート層の役割は、「データを通信相手に届けること」であり、通信相手のアプリケーション層にあるどのプロトコルに渡すかまで責任を持ちます。

TCPとUDPの違い

トランスポート層は上記の役割を担いますが、それを実現しているプロトコルがTCPUDPです。取り扱うデータの性質によって使用するプロトコルが異なります。

プロトコル 取り扱うデータの特徴
TCP 信頼性が必要とされるデータ Web、メール、ファイル共有など
UDP 即時性が必要とされるデータ DNS、音声、映像など

まとめると、TCP通信相手にデータを確実に届ける(ような仕組み)けど、通信に時間がかかるプロトコルであり、UDPデータを送ったら送りっぱなしで信頼性は低いけど、通信に時間がかからないプロトコルという特徴を持っています。

なぜ通信にかかる時間に違いがあるのか?

なぜTCPUDPとでは、通信にかかる時間に違いがあるのでしょうか。これはTCPUDPでのやりとりの様子をそれぞれ知ることで理解することができます。

今回はまずTCPに則った通信が実際にどのように行われるかを紹介していきます。

TCPでの通信の流れ

network-通信の流れ.png

1. 準備(ソケットの作成)

Webブラウザ

アプリケーション(ここではWebブラウザ)がSocketライブラリのsocketというプログラムを呼び出して、プロトコル・スタックにソケットを作成するよう依頼します。

クライアント側のプロトコル・スタック

ソケットひとつ分のメモリー領域を確保することで、そこにソケットの制御情報を記録していく準備を行います。この段階では初期状態であることを記録します。

2. 接続(three-way handshake)

network-3ウェイ・ハンドシェイク.png

Webブラウザ

WebブラウザがSocketライブラリのconnectを呼び出して、プロトコル・スタックに接続処理を依頼します。

クライアント側のプロトコル・スタック

クライアントがサーバに対して「通信しましょう!」という合図を送ります。

具体的に説明すると、クライアント側のプロトコル・スタックが「送信元と宛先のポート番号の情報」と「コントロール・ビットのSYNを1に設定した」TCPヘッダーを作成し、それをサーバ側のプロトコル・スタックに送信します。

サーバ側のプロトコル・スタック

受け取ったTCPヘッダー内の宛先ポート番号からソケットを特定します。ソケットが特定できた場合は、そのソケットに接続動作が進行中という情報を記録します。

そのあと、「受け取りました!」という事実と「通信しましょう!」という合図をクライアントに送り返します。

具体的に説明すると、サーバ側のプロトコル・スタックが「送信元と宛先のポート番号の情報」と「コントロール・ビットのSYNACKを1に設定した」TCPヘッダーを作成し、それをクライアント側のプロトコル・スタックに送り返します。

クライアント側のプロトコル・スタック

返ってきたTCPヘッダーのSYNビットが1であれば、ソケットにサーバ側に接続完了を示す情報を記録します。

最後にTCPヘッダーを受け取ったことをサーバ側に伝えるために、ACKビットが1のTCPヘッダーをサーバに送り返して、サーバがそれを受け取った時点で、接続完了となります。

3. 送信(リクエスト・メッセージの送信)

network-データ送受信.png

Webブラウザ

Socketライブラリのwriteプログラムを呼び出して、送信データ(ここではリクエスト・メッセージ)を指定したデータ長に分割した状態でプロトコル・スタックに渡します。

クライアント側のプロトコル・スタック

MSS(ヘッダーを除いて1つのパケットで運べるTCPデータの最大長)を超えるか、ある一定時間待った後に、バッファ・メモリー領域にたまったデータを送信するようにします。

またバッファ・メモリー領域にたまったデータがMSSを超える場合は、MSSのサイズに分割してデータ送信を行うようにします。

クライアント側のプロトコル・スタックは、データを分割する際にデータ断片の先頭が通信開始してから何バイト目に相当するかを数えておきます。そしてその数をシーケンス番号としてTCPヘッダーに記載します。

サーバ側のプロトコル・スタック

サーバ側のプロトコル・スタックがデータ断片をしたら、シーケンス番号にデータ断片のバイト数を加算したACK番号をTCPヘッダーに追加します。そうすることで、クライアント側のプロトコル・スタックに何バイト目までデータを受け取ったことを伝えます。

こうすることで、データの取りこぼしを検知することができます。例えば、ACK番号1001までデータを受信したのに、次に受信したデータのシーケンス番号が2001だった場合、1001~2001までのデータが抜けてしまっていることにわかります。

また送信したデータに対応するACK番号が返ってこなかった場合、送信側がデータを送り直すという強力な仕組みを備わっています。

network-データ.png

このような仕組みによって、データを確実に通信相手に届けるようにしています。

4. 受信(レスポンス・メッセージの受信)

3.と逆になるだけなので省略

5. 切断(ソケットの抹消)

network-切断処理.png

サーバ側のアプリケーション

サーバ側のアプリケーションがSocketライブラリのcloseを呼び出して、サーバ側のプロトコル・スタックに切断処理を依頼します。

サーバ側のプロトコル・スタック

サーバ側のプロトコル・スタックがコントロール・ビットのFINを1にセットしたTCPヘッダーを作成し、クライアントに送信します。その際に、サーバ側のソケットに切断動作に入ったという情報も記録します。

クライアント側のプロトコル・スタック

FINが1にセットされたTCPヘッダーを受けとったら、受け取ったことをサーバ側に知らせるために、ACK番号を送り返します。

Webブラウザ

WebブラウザがSocketライブラリのreadプログラムを呼び出すことで、クライアント側のプロトコル・スタックにより、データを全て受信したことを把握します。それがきっかけとなって、WebブラウザがSocketライブラリのcloseプログラムを呼び出して、クライアント側のプロトコル・スタックに切断処理を依頼します。

クライアント側のプロトコル・スタック

クライアント側のプロトコル・スタックも、コントロール・ビットのFINを1にセットしたTCPヘッダーを作成し、サーバに送信します。すると、サーバからACK番号が返ってくるはずなので、サーバとのやりとりが終了します。

まとめ

TCPに則った通信では、特定のデータ長に分割したデータ断片をクライアントとサーバがお互いに確認を取り合いながら送受信を行う。途中でデータの取りこぼしなどがあったら再送信することで、確実に全てのデータを送受信できる仕組みになっている。

参考にした本

所感

TCPは奥が深すぎます。。。今回この記事でまとめきれなかったことも数多くあります。。。ウィンドウ・サイズを使って効率的に通信を行う仕組みなどもまとめたかったのですが、時間の都合上ここまでにしました。

次回はUDPの仕組みを紹介して、TCPUDPの違いについてまとめようと思います。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8