この記事シリーズでは、インターネットで用いられている通信プロトコルであるTCP/IPで、通信が送信元から宛先に届くまでに起こっていることをミクロ視点で解説します。
あらゆる技術について言えることですが、コンピュータ内部で起こっているミクロな挙動の理解は、その後の技術の学習や実務で必ず役に立ちます。
- ネットワークエンジニアになりたい人
- サーバ担当でネットワークも知っておきたい人
- IT系の営業で話の幅を広げたい人
- とにかくITの教養を身につけたい人
このような人たちにオススメの記事です。
是非ともご覧ください。
【本シリーズ】
目次
TCPヘッダー、UDPヘッダーについて
第1回で解説した、L4ヘッダーであるTCPヘッダーとUDPヘッダーについて再度記載します。
L4ヘッダーは通信を制御する情報を示すヘッダーです。
送信するデータを分割した後、IPヘッダーの付与の前に付与されます。
送信データ(ペイロード)にL4ヘッダーが付与されたものをセグメントといいます。
この通信の制御はOSによって行われます。
通信制御にはいろいろなプロトコルがありますが、よく使われるのは、TCP(Transmission Control Protocol)と、UDP(User Datagram Protocol)です。
それぞれ特徴・向き不向きがあります。
いずれも通信を完了させるためにとても重要なプロトコルです。頑張って理解しましょう。
IPヘッダのプロトコル番号
L4ヘッダーの解説の前に、IPヘッダーのプロトコル番号について説明します。
IPヘッダーは以下の通りです。
この中にある8ビットのプロトコル番号というもので、上位のプロトコルが何かを示しています。
IPパケットを受信した機器は、このプロトコル番号を見て「TCPか?UDPか?(あるいはそれ以外か?)」を判別します。
ちなみに、TCPのプロトコル番号は6で、UDPのプロトコル番号は17です。
TCPとUDPのポート番号
TCPとUDPには、ポート番号というものがあります。
※上述のプロトコル番号とは別物です。混同しないようにしましょう。
一言で説明すると、ホームページか、メールか、音声通話か等のサービス(≒アプリケーション)を識別する番号です。
MACアドレスでネットワーク内の宛先がわかりました。
IPアドレスでネットワーク外の宛先がわかりました。
この2つの情報があれば宛先のコンピュータ(のI/F)に到達できます。
そして、このポート番号で宛先コンピュータ内のどのアプリケーションでデータを処理すればいいのかがわかるのです。
ポート番号も、IPアドレスやMACアドレスと同じように、ヘッダーに送信元と宛先の両方が格納されます。
送信元、宛先共に16ビットで、0番から65535番まであります。
そして、通信を受け取ったコンピュータ(サーバーなど)は、返信する際に送信元のポート番号と宛先のポート番号を入れ替えて返信します。
これは返信を受け取った送信元コンピュータがどのアプリケーション(ブラウザ、メールソフト等)で発信していたかを判断するためです。
このポート番号(サービス識別子)は主なサービスではあらかじめ決められています。これをWell Knownポート番号と言います。
主なものは以下の通りです。
TCP(Transmission Control Protocol)
TCPはその名の通り転送を制御するプロトコルです。データの送受信を最初から最後まで確認します。
この記事ではTCPのうち、
- 通信の開始(3ウェイハンドシェイク)
- 送受信データの確認
- ウインドウサイズ
- 輻輳制御
- 通信の終了
について解説します。
TCPヘッダーの構造は以下の通りです。
これからの解説には、個々のフィールドの値も関わってきますので、軽く眺めておきましょう。
通信の開始(3ウェイハンドシェイク)
TCPで通信を開始する場合に必ず行われるのが、3ウェイハンドシェイクです。(名前だけなら聞いたことがある人も多いのではないでしょうか?)
これは文字通り、通信を3回やり取りすることにより、お互いが「通信が可能な状態です」ということを確認することをいいます。
そして、この3ウェイハンドシェイクが完了した状態を、(TCPの)セッションが確立している状態といいます。
3ウェイハンドシェイクは、TCPの中のコントロールフラグフィールドで制御されます。
コントロールフラグフィールド全部で6ビットです。
- URG
- ACK
- PSH
- RST
- SYN
- FIN
の6ビットで構成されています。
TCPの3ウェイハンドシェイクは以下の手順で行われます。
- 通信を開始したいコンピュータが、宛先のコンピュータ宛に「SYN」ビットが「1」となっているTCPヘッダーを送る。
- 上記のTCPヘッダーを受領した対向コンピュータは、通信を開始してもよければ「ACK」ビットが「1」、「SYN」ビットが「1」となっているTCPヘッダーを返信する。
- 最初のコンピュータは対向コンピュータから「SYN:1」「ACK:1」のTCPヘッダーを受領したことを確認するため、「ACK:1」のTCPヘッダーを送信する。
このデータのやり取りにより、TCPセッションが確立します。
以下に図示します。
送受信データの確認
TCPでは、送信しているデータがちゃんと受信されているかを確認します。
この確認は、TCPヘッダーの中のシーケンス番号と確認応答番号で行います。
シーケンス番号は、データを送信する側で送信データのバイト数を加算します。(つまりは1000バイトのパケットを送信すると、シーケンス番号を+1000します)
これにより、受信側は送信データを順番に並べて復元できます。
確認応答番号は、「シーケンス番号+受信データのバイト数」が設定され、送信元に返信されます。
これにより、送信側は届いていないデータがないかを確認できます。
確認応答番号に抜け漏れがある場合には、送信側はデータを再送します。
この機能により、仮に経路の途中でパケットの喪失などがあった場合でも、最終的には全てのデータを相手に届けることができます。
ウインドウサイズ
上図では、1パケット送信後に1確認応答をしています。
しかし、データを受信する側の処理能力に余裕があれば、一気にデータを送信した方が効率がいいです。
(パケットの受信順番が前後しても、シーケンス番号を見れば、正しい順番に並べ替えることができます)
データを受信する側の処理能力を表したのがウインドウサイズです。
ウインドウサイズは16ビットの値で処理能力を表現します。
このウインドウサイズは、常に値が変化します。
処理能力に余裕がある場合には、大きな値を設定したTCPヘッダ(+データ)を送信しますし、余裕がなければ小さな値で送信します。
このフィールドの値により、お互いの処理能力についても情報を共有しているわけです。
輻輳制御
上記のウインドウサイズは、送受信をするコンピュータの処理能力で通信量を制限する機能です。
輻輳制御は、経路上のネットワークの処理能力を測り通信量を制限する機能です。
実際の通信では経路上のネットワークが輻輳している場合があります。
ネットワークが輻輳しているのにデータを送り続けるのは、あまりいいことではありませんし、通信の効率もよくないです。(処理しきれない通信を破棄する処理にも、コンピュータのリソースを使います)
そこで、TCPでは輻輳制御を行います。
輻輳制御のアルゴリズムはいくつかあります。
まず、スロースタートというアルゴリズムがあります。
これは通信を行う際に「いきなり全速力でパケットを送信するのではなく、最初に少しだけパケットを送信して様子を見る」というアルゴリズムです。
続いて、輻輳回避というアルゴリズムがあります。
これは「パケットの損失などでネットワークの輻輳を検知した際に、パケットの送信量を減らす」というアルゴリズムです。
これにより、通信の輻輳を回避します。
その後、問題がなさそうなら徐々に通信量を上げていきます。
通信の終了
TCPでは、通信を終了する場合にもきちんと情報のやり取りをします。
これを「セッションの終了」と言います。
セッションの終了では4ウェイのやり取りをします。
3ウェイの時と同じくコントロールフラグの値で情報をやり取りします。
まず、通信を終了するコンピュータから、TCPヘッダに「FIN:1」「ACK:1」のビットが入ったパケットを送信し、通信終了を通知します。
そして、通信終了のパケットを受け取ったコンピュータは、TCPヘッダに「ACK:1」のビットが入ったパケットを送信し、通信終了の返答をします。
続いて、通信終了のパケットを受け取ったコンピュータからも、TCPヘッダに「FIN:1」「ACK:1」のビットが入ったパケットを送信し、通信終了を通知します。
最後に、通信を終了するコンピュータも、TCPヘッダに「ACK:1」のビットが入ったパケットを送信し、通信終了の返答をします。
これで、TCPセッションの終了が完了します。
UDP(User Datagram Protocol)
続いてはUDPです。
まずはUDPヘッダを図示します。
TCPと比べると大分シンプルです。
端的にいうと、UDPでは上位プロトコル(サービス)を示すポート番号以外は、特に何もしません。
TCPで行っていたような通信制御はほとんどやりません。
ヘッダのデータ量の小ささ(TCPは20バイト、UDPは8バイト)もそうですが、それ以上に通信制御を行わないために、通信が軽くなります。
まとめ
個人的な感想としては、最初にTCPの通信制御について習った時には驚きました。
通信相手や経路上のネットワークへの考慮など、意外と色々な機能を持っていると感銘を受けたものです。
システム障害発生時には、ネットワークと関係ない障害でも、大抵ネットワークチームが悪者扱いされます。
そんな時でもTCPなどの知識があれば、ネットワーク外で発生した問題に対処できる場合があります。
昔話になりますが、
メールが遅延している。メールを送信してから5時間くらい後に受信された。
これはネットワークの遅延が原因だ。
などとサーバーチームに言われたことがあります。
この記事で解説したTCPのセッションについて理解していたので、すぐに回答できました。
仮にネットワークが5時間遅延しても、TCPセッションはとっくの昔にタイムアウトするはずです。メールサーバーの再送ログを確認してもらうことで対応完了しました。
※ちなみに、パケットがネットワーク内に5時間も滞留するはずはありませんが、ネットワーク視点から説明してもなかなか聞き入れてもらえないものです。
次回は、このTCP/IP通信シリーズで飛ばしてしまった用語などの補足説明の記事を投稿しようと思っています。
次回もお楽しみに!
それでは (*゚▽゚)ノ