Blog
本記事の目的
サーバーに送信するためのHTTPリクエストは、ブラウザが作成します。
この記事では、ブラウザが作成したリクエストがプロトコル・スタックを通じて送信され、サーバーからの応答(レスポンス)が返ってくるまでの一連の流れを学びます。普段意識することの少ない、OS内部でのプロトコル・スタックの働きに注目しながら解説していきます。
プロトコル・スタックとは
プロトコル・スタックとは、ネットワーク通信を実現するための一連の通信プロトコルの層構造を指します。
各層が独立した役割を持ち、階層的に連携することでデータの送受信が効率的かつ信頼性をもって行えるようになります。
なかでもTCP、UDP、IPは、プロトコルスタックの中核を成すプロトコルで、データがネットワークを通じて確実に送受信されるために重要な役割を果たします。
ブラウザでリクエストを作成
↓
プロトコルスタックで加工(TCP/UDP → IP → LANドライバ)※ 本記事ではここを主に学習します
↓
LANドライバが物理層へ送信(電気信号や無線波としてデータを送信)
... といった感じでデータを送信します!
TCP
ブラウザやメールなど、データの信頼性や順序が重要な通常のアプリケーションで利用。TCPは信頼性を保証するため、データの再送や順序の確認を行います。
UDP
DNSサーバーへの問い合わせや音声通話、ストリーミングなど、軽量でリアルタイム性が求められる通信に利用されます。UDPは信頼性を保証しない代わりに、迅速なデータ送受信が可能です。
IP
パケット送受信のルーティング(経路指定)を担当し、ネットワーク間でデータを運ぶ役割を果たします。
プロトコル・スタックは制御情報を見ながら動作する
プロトコルスタックは、内部に通信を管理するための制御情報を保持するメモリ領域を持っています。
この領域には、通信関連の重要な情報が記録されています。具体的には、以下のようなデータが含まれます。
- 通信相手のIPアドレス
- ポート番号(アプリケーションの識別に使用)
- 通信の進行状況(進行ステータス)
- パケットの送受信状態(再送要求や受信確認など)
この制御情報を利用して、プロトコルスタックはデータの送受信や接続の管理を行います。
また、これらの制御情報をまとめて「ソケット」と呼んだりします。
例えば、データ送信時はソケットに保存されているIPアドレスやポート番号を用いて、相手にデータを送信します。送信後、TCPの場合、受信完了を知らせる確認応答(ACK)が返ってくるのが基本です。
もし、いくら待っても確認応答が来ない場合、TCPは「途中でデータが消えた」と判断し、再送信を行います。この際、再送信のタイミングを決定するために、ソケットは経過時間や再送回数などの情報を保持しています。これにより、一定時間内に確認応答が届かない場合には、適切に再送信処理を行うことができます。
また、タイムアウト時間(確認応答が来ない場合の再送までの時間)は、動的に調整されることがあり、ネットワークの状態に応じて再送信の頻度や間隔が変化します。
実際の流れを↓で見ていきます。
1. ソケットの作成
ネットワーク通信を行うために、TCPプロトコルはまず「ソケット」を作成します。ソケットの作成時には、まずソケット用のメモリ領域が確保されます。この時点では、まだIPアドレスやポート番号といった通信に必要な制御情報は設定されていません。ただし、この過程でソケットを識別するためのディスクリプタが生成され、アプリケーション(例えば、ブラウザ)に通知されます。このディスクリプタは、後続の通信でソケットを一意に識別するために使用されます。
2. ソケットの接続
次に、作成したソケットを使用して、目的のサーバーに接続します。接続というと少し難しく聞こえるかもしれませんが、実際にはクライアント側(ブラウザなど)とサーバーが、お互いの制御情報を交換するプロセスです。クライアントはサーバーに対して、「私はIPアドレス(xxx.xxx.xxx.xxx)のポート番号(xxx)から通信を開始します。通信してもよろしいでしょうか?」というリクエストを送ります。
サーバーはクライアントからのリクエストを受け取ると、そのリクエストを検証し、通信可能であれば接続を許可します。この過程で、クライアントとサーバーはお互いのソケットに相手の通信情報(IPアドレス、ポート番号など)を保存し、通信の準備が整います。
3. データの送受信
接続が確立した後は、データの送受信が行われます。データを送信するためには、ソケットを通じて通信相手にデータを送ります。また、相手からのレスポンスを受け取るためには、ソケットが受信したデータを取り出して処理することになります。
例えば、データを送信した後、通信相手から「受け取りました」という確認のレスポンスが戻ってきた場合、それを受け取って通信が完了したことを確認します。
データの送受信は「パケット」という単位で分割して行われます。パケットは、送信するデータを小さな塊に分けたもので、ネットワーク上を効率的に転送するために重要な役割を果たします。パケットごとに送信元や宛先の情報、データ本体などが含まれており、受信側でこれらを組み合わせて元のデータに復元します。
このパケット通信の詳細については、また別の記事でじっくりと学習します。パケットの構造や送信の仕組みは、ネットワーク通信の理解を深める上で重要ですが、かなりボリュームがあるため、別途詳しく説明します!
4. ソケットの抹消
通信が完了した後は、ソケットを閉じる必要があります。TCPでは接続終了時にFINビットを用いて、以下のような流れで処理が進みます。
①クライアントからの終了通知
クライアントはTCPヘッダーのFINビットを1に設定したパケットをサーバーに送信し、通信を終了したい意思を伝えます。
②サーバーの確認応答
サーバーはFINパケットを受け取り、それに対する確認応答(ACKパケット)をクライアントに返します。
③サーバーからの終了通知
サーバー側も終了準備が整うと、TCPヘッダーのFINビットを1に設定したパケットをクライアントに送信します。
④クライアントの確認応答
クライアントはサーバーのFINパケットを受け取り、確認応答(ACKパケット)を返します。これにより接続は正式に終了します。
終わり
今回は、ブラウザで作成されたリクエストをOS内部のプロトコル・スタックが処理してサーバーとのやり取りを行う仕組みについて学びました。
普段何気なく行っている通信が、実はここまで複雑な処理を経て成り立っていることは、勉強して初めて気付くことでした。
いつかの自分のために役にたつかもしれないですね:)
次回は、今回触れた「パケット」という単位や、データをどのように分割し、再構築しているのかについて詳しく学んでいきます!
これを知ることで、なぜデータが「壊れずに正確に届くのか」が理解できるようになるはずです。
それでは、ここまでお付き合いいただきありがとうございました:)
CONTACT
あくまでも本業がメインですが、休日や業務の隙間時間は個人でも動いております。
もしお手伝いできることがあれば、お気軽にお問い合わせください。