net_TCP/UDPについて

11TCP/UDPについて

TCP(Transmission Control Protocol)

TCPは、信頼性の高いデータ通信を提供するプロトコルです。このプロトコルは、データの送受信を行う前に接続を確立し、データの順序やエラーを管理します。たとえば、HTTP通信やファイル転送、メール送信などに使用されます。WebブラウザがWebサーバーからデータを取得する際や、FTP(File Transfer Protocol)を使った大きなファイルの転送、SMTP(Simple Mail Transfer Protocol)やIMAP(Internet Message Access Protocol)、POP3(Post Office Protocol)を使ったメールの送受信など、信頼性が求められる場面でTCPが利用されます。

TCPの主な特徴を以下の表にまとめます.

機能説明
接続の確立データ送信を開始する前に3ウェイハンドシェイクを行い、確実に接続を確立します。
信頼性の確保データが正しく送信されることを保証し、受信側は確認応答(ACK)を返し、エラー発生時に再送します。
順序制御データが送信された順序通りに到着することを保証し、シーケンス番号を使って順序を管理します。
フロー制御送信側が受信側のバッファ容量を超えてデータを送信しないように調整します。

UDP(User Datagram Protocol)

UDPは、軽量で高速なデータ通信を提供するプロトコルです。このプロトコルは、接続の確立や順序制御を行わず、データグラムを直接送信します。たとえば、動画や音声のストリーミング、オンラインゲーム、ドメイン名の解決を行うDNS(Domain Name System)などに使用されます。ストリーミングでは多少のデータ損失が許容されるためリアルタイム性を重視するUDPが適しており、オンラインゲームでは遅延を最小限に抑えるためにUDPが利用されます。また、DNSクエリはクエリの速度を重視するためUDPを使用します。

UDPの主な特徴を以下の表にまとめます:

機能説明
接続の確立データ送信前に接続を確立する手順がありません。
信頼性データの送信が保証されず、エラー検出や再送機能がありません。
順序保証データの順序を保証しません。
オーバーヘッド追加の制御がないため、オーバーヘッドが少なく高速です。

TCPとUDPの違い

以下の表に、TCPとUDPの違いをまとめます.また次の章では、TCPとUDPの主要な違いに注目して、特にTCPの3ウェイハンドシェイクについて詳しく解説します。この部分は理解することが重要であり、両プロトコルの動作原理を深く理解する鍵となります。

機能TCPUDP
接続の確立3ウェイハンドシェイクを行う接続の確立手順がない
信頼性高い(エラー検出と再送機能あり)低い(エラー検出と再送機能なし)
順序制御ありなし
フロー制御ありなし
オーバーヘッド大きい小さい
使用例HTTP通信、ファイル転送、メール送信ストリーミング、オンラインゲーム、DNSクエリ

3ウェイハンドシェイクとは(概要)

3ウェイハンドシェイクは、TCPで新しい接続を確立するためのプロセスです。このプロセスにより、クライアントとサーバーは互いに接続を確立する意思があることを確認し、信頼性の高い通信が可能となります。以下の表に、3ウェイハンドシェイクのステップをまとめます。

ステップ説明
SYN送信クライアントがサーバーに接続要求を送信します(SYNパケット)。
SYN-ACK送信サーバーがクライアントのSYNパケットを受信し、SYN-ACKパケットで応答します。
ACK送信クライアントがサーバーのSYN-ACKパケットを受信し、ACKパケットで応答します。

このプロセスを経ることで、クライアントとサーバーは互いに接続を確立する意思を確認し、信頼性の高い通信が可能となります。

3ウェイハンドシェイクが必要な理由

3ウェイハンドシェイクがなぜ必要なのか掴みづらいため、3ウェイハンドシェイクの目的について表にまとめました.

目的説明
信頼性の確保クライアントとサーバーが接続準備が整っていることを確認し、双方が通信を開始する意思があるかを保証します。
初期シーケンス番号の同期接続開始時にシーケンス番号を同期することで、送られてくるデータパケットの順序を正確に把握し、データの整合性を維持します。
フロー制御の確立双方のデバイスがデータを効率良く送受信できるように、ウィンドウサイズやその他の通信オプションを交換し、データ転送の制御を最適化します。

実際のTCP/UDPの通信を確認しよう

実際にTCPとUDPそれぞれの通信を監視して、3ウェイハンドシェイクについて理解を深めましょう.

通信シナリオ(TCP)

東京にあるサーバが特定のポートで通信を待ち受けています。このサーバへ、北海道のクライアントが接続要求を行い、接続が成立すると両者間でデータのやり取りを開始します。通信が終了した後、接続は適切に切断されます。このプロセス全体を、tcpdumpコマンドを使用してパケットレベルで追跡し、通信内容を詳細に確認します。

ncコマンド

今回の実験でサーバの通信の待ち受けと接続にncコマンドを用います.

ncコマンドとは、ネットワークを通じてデータを送受信するためのツールです。簡単に言うと、コンピュータ間で話をするための電話のようなものです。このツールを使うことで、TCPやUDPといった通信規約を用いて、特定のアドレスとポートに接続することができます。

通信の待ち受け

東京のあるデバイスで、TCP通信の待ち受けを開始させます.

root@b9f15438cc2c:/# ip netns exec tokyo nc -l -p 12345

サーバへの接続

東京にあるサーバに対して、北海道にあるデバイスでTCPによる接続を試みます

root@b9f15438cc2c:/# ip netns exec hokkaido nc 172.0.2.254 12345

サーバに接続した時のtcpdumpのログ

root@b9f15438cc2c:/home/shell# ip netns exec tokyo tcpdump -i any
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
05:03:50.210079 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [S], seq 3290169199, win 64240, options [mss 1460,sackOK,TS val 4025254551 ecr 0,nop,wscale 7], length 0
05:03:50.210121 tokyo-hokkaido Out IP 172.0.2.254.12345 > 172.0.2.1.48676: Flags [S.], seq 1995298183, ack 3290169200, win 65160, options [mss 1460,sackOK,TS val 4254722095 ecr 4025254551,nop,wscale 7], length 0
05:03:50.210143 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [.], ack 1, win 502, options [nop,nop,TS val 4025254551 ecr 4254722095], length 0

それぞれのログの意味について解説していきます.

1. SYN(Synchronize)パケット送信

クライアントがサーバーに接続要求を送信します。これがSYNパケットで、初期シーケンス番号を含みます。

05:03:50.210079 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [S], seq 3290169199, win 64240, options [mss 1460,sackOK,TS val 4025254551 ecr 0,nop,wscale 7], length 0
フィールド説明
Flags [S]SYNフラグが設定されています。
seq 3290169199初期シーケンス番号。

2. SYN-ACK(Synchronize-Acknowledge)パケット送信

サーバーがSYNパケットを受け取ると、SYNフラグとACKフラグが設定されたパケットで応答します。これにより、サーバーの初期シーケンス番号も送信されます。

05:03:50.210121 tokyo-hokkaido Out IP 172.0.2.254.12345 > 172.0.2.1.48676: Flags [S.], seq 1995298183, ack 3290169200, win 65160, options [mss 1460,sackOK,TS val 4254722095 ecr 4025254551,nop,wscale 7], length 0
フィールド説明
Flags [S.]SYNフラグとACKフラグが設定されています。
seq 1995298183サーバーの初期シーケンス番号。
ack 3290169200クライアントのシーケンス番号に対するACK。

3. ACK(Acknowledge)パケット送信

クライアントはサーバーのSYN-ACKパケットを受け取ると、ACKフラグを設定したパケットで応答し、接続が確立されます。

05:03:50.210143 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [.], ack 1, win 502, options [nop,nop,TS val 4025254551 ecr 4254722095], length 0
フィールド説明
Flags [.]ACKフラグが設定されています。
ack 1サーバーのシーケンス番号に対するACK。

サーバへのパケット送信

東京にあるサーバに対して、北海道にあるデバイスからメッセージを送信します

root@b9f15438cc2c:/# ip netns exec hokkaido nc 172.0.2.254 12345
tokyo

東京にあるサーバは、メッセージを受け取ります

root@b9f15438cc2c:/# ip netns exec tokyo nc -l -p 12345
tokyo

接続が確立された後、データの送受信が行われます。この際、ACKフラグが設定されたパケットが使用され、データの正しい受信を確認します。ログを確認してみましょう.

05:03:52.864967 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [P.], seq 1:7, ack 1, win 502, options [nop,nop,TS val 4025257206 ecr 4254722095], length 6
05:03:52.865006 tokyo-hokkaido Out IP 172.0.2.254.12345 > 172.0.2.1.48676: Flags [.], ack 7, win 510, options [nop,nop,TS val 4254724750 ecr 4025257206], length 0
フィールド説明
Flags [P.]PSHフラグとACKフラグが設定されています。データを即時に処理することを指示します。
ack 7受信したデータに対するACK。

通信終了とFINフラグ

TCPを用いた通信では接続終了時にも通信を行い、4ウェイハンドシェイクと呼ばれます。 通信終了時には、接続を終了する意思を相手に伝えるためにFINフラグを使用します。

通信を待ち受けているサーバを止めます

root@b9f15438cc2c:/# ip netns exec tokyo nc -l -p 12345
tokyo
^C

1. FINパケット送信

サーバーが接続を終了したい場合、FINフラグを設定したパケットを送信します。

05:03:56.544954 tokyo-hokkaido Out IP 172.0.2.254.12345 > 172.0.2.1.48676: Flags [F.], seq 1, ack 7, win 510, options [nop,nop,TS val 4254728430 ecr 4025257206], length 0
フィールド説明
Flags [F.]FINフラグとACKフラグが設定されています。
seq 1シーケンス番号。
ack 7これまで受信したデータに対するACK。

2. ACKパケット送信

クライアントはFINパケットを受け取り、ACKフラグを設定したパケットで応答します。

05:03:56.545682 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [.], ack 2, win 502, options [nop,nop,TS val 4025260886 ecr 4254728430], length 0
フィールド説明
Flags [.]ACKフラグが設定されています。
ack 2FINパケットに対するACK。

北海道デバイスからの東京サーバへの接続をやめます

root@b9f15438cc2c:/# ip netns exec hokkaido nc 172.0.2.254 12345
tokyo

1. クライアント側のFINパケット送信

クライアントも接続を終了するためにFINフラグを設定したパケットを送信します。

05:03:58.632962 tokyo-hokkaido In  IP 172.0.2.1.48676 > 172.0.2.254.12345: Flags [F.], seq 7, ack 2, win 502, options [nop,nop,TS val 4025262974 ecr 4254728430], length 0
フィールド説明
Flags [F.]FINフラグとACKフラグが設定されています。
seq 7シーケンス番号。
ack 2サーバー側のFINパケットに対するACK。

2. 最終ACKパケット送信

サーバーはクライアントのFINパケットを受け取り、ACKフラグを設定したパケットで応答します。

05:03:58.633026 tokyo-hokkaido Out IP 172.0.2.254.12345 > 172.0.2.1.48676: Flags [.], ack 8, win 510, options [nop,nop,TS val 4254730518 ecr 4025262974], length 0
フィールド説明
Flags [.]ACKフラグが設定されています。
ack 8クライアント側のFINパケットに対する最終ACK。

まとめ

この実験を通じて、TCPの通信が信頼性の高い通信であるかが伝わったと思います。特に、通信を始める前の「3ウェイハンドシェイク」という手順が、その信頼性を高める大きな役割を果たしています。この手順によって、コンピュータ同士がしっかりと通信を始める準備ができているかを確認し合います。また、データを送る際には、受け取ったことを相手に確認してもらう「確認応答」が行われ、何か問題があれば再送を行うことができます。通信の終わりには、両方のコンピュータが通信を終了することに同意し、きちんと「通信」を終えることが確認されます。これらのプロセスにより、TCPはデータが正確に、そして順序良く伝えられるようになっていることが分かっていただけたかと思います.次の節でUDPで通信した際のパケットの状態を見てみましょう.

通信シナリオ(UDP)

東京にあるサーバが特定のポートで通信を待ち受けています。このサーバへ、北海道のクライアントが接続要求を行い、接続が成立すると両者間でデータのやり取りを開始します。通信が終了した後、接続は適切に切断されます。このプロセス全体を、tcpdumpコマンドを使用してパケットレベルで追跡し、通信内容を詳細に確認します。

通信の待ち受け

東京のあるデバイスで、TCP通信の待ち受けを開始させます.

root@b9f15438cc2c:/# ip netns exec tokyo nc -u -l -p 12345

サーバへの接続

東京にあるサーバに対して、北海道にあるデバイスでTCPによる接続を試みます

root@b9f15438cc2c:/# ip netns exec hokkaido nc -u 172.0.2.254 12345

サーバに接続した時のtcpdumpのログ

root@b9f15438cc2c:/home/shell# ip netns exec tokyo tcpdump -i any
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

上記のログ出力からわかるように、UDPはTCPと異なり、接続確認プロセス(3ウェイハンドシェイク)を省略します。これにより、UDPでは通信の開始前に相手側との接続状態を確認することがありません。データの送受信は直接的に始まり、そのために発生するエラーやデータの喪失は自動的には検出されません。この「非接続性」がUDPの速度を向上させる一方で、TCPに比べて信頼性やデータ整合性が低くなる原因となります。

サーバへのパケット送信

東京にあるサーバに対して、北海道にあるデバイスからメッセージを送信します

root@b9f15438cc2c:/# ip netns exec hokkaido nc -u 172.0.2.254 12345
tokyo

東京にあるサーバは、メッセージを受け取ります

root@b9f15438cc2c:/# ip netns exec tokyo nc -u -l -p 12345
tokyo

サーバのログ

root@b9f15438cc2c:/home/shell# ip netns exec tokyo tcpdump -i any
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
05:05:09.759687 tokyo-hokkaido In  IP 172.0.2.1.38449 > 172.0.2.254.12345: UDP, length 6

上記のログから、UDPではメッセージ送信のためのパケットのみが送信されており、メッセージ送信においてもTCPのような接続確認が行われていないことがわかります.

通信終了とFINフラグ

通信を待ち受けているサーバを止めます

root@b9f15438cc2c:/# ip netns exec tokyo nc -l -p 12345
tokyo
^C

北海道デバイスからの東京サーバへの接続をやめます

root@b9f15438cc2c:/# ip netns exec hokkaido nc 172.0.2.254 12345
tokyo

サーバのログ

root@b9f15438cc2c:/home/shell# ip netns exec tokyo tcpdump -i any
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
05:05:09.759687 tokyo-hokkaido In  IP 172.0.2.1.38449 > 172.0.2.254.12345: UDP, length 6

上記のログ出力からUDPでは、サーバーにパケットを送信する際や通信を終了する際にも、TCPで見られるようなパケットの受領確認や通信終了の確認(4ウェイハンドシェイクによるFINパケットの交換)が行われません。UDPはデータの送受信において確認応答を行わないため、パケットの損失や順序の混乱があっても検出されることはありません。この特性は、通信の迅速性を求めるアプリケーションには有利ですが、TCPと比較して通信の信頼性は劣ります。通信終了時にも特にプロトコルレベルでの終了確認がないため、セッションは形式的な終了プロセスなしに静かに終了します。

まとめ

このUDP通信シナリオから、UDPとTCPの違いが顕著に見えます。UDPは接続確立のプロセスを行わず、データの送受信を直接開始するため、通信のセットアップが迅速です。これに対し、TCPでは3ウェイハンドシェイクを用いて接続の確認を行い、確実なデータ伝送を保証します。UDPではこのような接続確認が省略されるため、通信のオーバーヘッドが少なく、より速いデータ転送が可能ですが、信頼性やデータの順序正確性は保証されません。したがって、UDPはリアルタイム通信など、速度が求められるアプリケーションに適しており、TCPはデータ整合性と信頼性が必要な場面で優れた選択肢となります。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です