webページが表示される仕組みについて[ネットワークはなぜつながるのか]

## はじめに

最近「ネットワークはなぜつながるのか」を読みました。

https://amzn.to/3OnCVat

<a href="https://www.amazon.co.jp/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC%EF%BC%92%E7%89%88-%E6%88%B8%E6%A0%B9-%E5%8B%A4-ebook/dp/B077XSB8BS?adgrpid=60120324664&hvadid=658902018842&hvdev=c&hvlocphy=1009308&hvnetw=g&hvqmt=b&hvrand=5914444874687365773&hvtargid=kwd-335360621497&hydadcr=27268_14678560&jp-ad-ap=0&keywords=%E3%81%AA%E3%81%9C%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%81%AE%E3%81%8B&qid=1684555535&sr=8-1&linkCode=li2&tag=fakseugoruesk-22&linkId=97f1fc7a39671247d1d3caa3ffa563e7&language=ja_JP&ref_=as_li_ss_il" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B077XSB8BS&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=fakseugoruesk-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=fakseugoruesk-22&language=ja_JP&l=li2&o=9&a=B077XSB8BS" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

しかし、ただ読んだだけでは学習の理解度が高まらないので、ラーニングピラミッドに則ってアウトプットとして解説を書きます

![learning_pyramid-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/018c11fc-4326-ba0e-c4d5-48f71d01db37.jpeg)

もし正しくないところなどあればコメントください！

### 学習の動機
私は普段webエンジニアとして働いています。
しかし、エンジニアとしての働き始めてから１年程度で、まだまだ知らないことがたくさんあります。

そのため、業務に役立つキャッチアップをしなければいけないと感じていて、特にwebページが表示される仕組みについてあまり詳しく知りませんでした。

自分がurlを入力してからwebページが表示されるまでに何が起こっているのか？

HTTP,TCP/IPなど、なんとなくどういうものかは知っているが、詳しい仕組みはわかっていませんでした。
今回はしっかりと学び直し、根本的な部分の理解を深めることで、日々の業務への貢献度が高まるなと感じました。

また、よく企業面接で「URLを入力してからwebページが表示されるまでの仕組みを解説してください」というの質問が出されます。

その際に適切に回答できたらかっこいいなと思ったから勉強しようと決意しました。

## データの流れ
![スクリーンショット 2023-05-20 13.10.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/2036e9ec-8f8a-e626-521a-a87c7a47eab2.png)

![スクリーンショット 2023-05-20 13.24.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/377fd72b-0896-f02f-513d-cd2138306063.png)


まず、あなたがhttps://client.example.comをブラウザに入力してEnterしたとします。

そうするとまず、ブラウザはURLを解析し、DNSサーバーに問い合わせを行い、URLからIPアドレスを特定します。

DNSサーバーからこのURLに対応するIPアドレスは"168.152.1.1だよ"とレスポンスが返ってくるので、そのIPアドレスをもとにwebサーバーにHTTPリクエストを送信します。

webサーバーはHTTPリクエストからHTTPレスポンスを返します。
ここにhtmlやjavascript,cssがあります。

webブラウザはwebサーバーから返却されたhtmlなどをレンダリングして、実際に表示するという流れです。

この流れを詳しく解説していきます。

## webブラウザ

#### URLの解析
![スクリーンショット 2023-05-20 13.33.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/80955681-9278-0649-60ce-b75f1dad4d48.png)

ブラウザはまずURLを解読します。
HTTPとはプロトコル、つまり約束事です。

#### HTTPについて

![スクリーンショット 2023-05-20 13.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/126081de-49e4-aeb2-973a-216e484ba5c9.png)

webサーバーにリクエストを送る際に、webサーバーに何をして欲しいのか伝える必要がありますが、そのフォーマットのことです。

HTTPのメソッドはたくさんありますが、実際に使われているのはほぼGETとPOSTです。

GETの場合はメッセージボディが空になります。なぜならデータの取得だけで送信は行わないから。

POSTの場合はメッセージボディに送信したいテキストが入ります。

ヘッダーフィールドはたくさん種類があります。
私が実際にこれを勉強した時はCORSエラーになった際にヘッダーの設定をしました。

https://atmarkit.itmedia.co.jp/fnetwork/rensai/netpro01/header-fields.html

ここではCORSエラーについては詳しく解説しませんが、フロントエンド開発時にAPIサーバーを利用する時など頻繁に遭遇すると思われるので、興味がある方は詳しく調べてみてください。

HTTPリクエストを送信したら、サーバーからはレスポンスが帰ってきます。

その結果には一行目にHTTPのステータスコードが返されます。

成功の場合は200~
リダイレクトは300~
クライアントエラーは400~
サーバーエラーは500~

つまりよく目にする404 not foundはクライアント側のエラーで、該当アドレスのページがないことなどが主な原因です。

このようにエラーの原因をある程度特定できるので、ステータスコードは非常に重要です。

https://developer.mozilla.org/ja/docs/Web/HTTP/Status

ちなみにこのHTTPリクエストとレスポンスはchromeのデベロッパーツールから実際のデータを確認することもできます。

![スクリーンショット 2023-05-20 13.55.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/367a24fb-6724-51e9-965c-fab208445d9a.png)

これを見るとqiitaのページを表示するためにGETメソッドを用いて、ステータスは200で成功していることがわかりますね。

Responseタブを開くと、返却されているhtmlも確認できます。

これがAPIサーバーとの通信になると、responseがjsonになったりします。

#### IPアドレス
ブラウザはURLを解読したり、HTTPメッセージを作ることはできますが、そのメッセージをネットワークに送ることはできません。
そのためOSに依頼して送信します。

その際にどのOSに送信するか判別するためにIPアドレスが必要になります。

IPアドレスを探す機能はSocketライブラリが提供しています。
Socketライブラリのリゾルバというものを利用します。

![スクリーンショット 2023-05-20 14.14.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/c06e5f87-dee0-7880-98d9-13331a1b997a.png)


### DNSサーバー
![スクリーンショット 2023-05-20 14.16.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/cdf4e9a4-a3ab-73c6-7a67-73ff9a2b8dae.png)

DNSサーバーは名前、クラス、タイプが一致するものを返します。
名前=www.examle.com
クラス=IN
タイプ=A

返答192.152.168

のような形ですね。

これは実際にドメインを登録したことがある人なら理解しやすいかと思います。
お名前.comなどにもこのような登録する項目が存在します。

#### ドメインの階層構造
![スクリーンショット 2023-05-20 14.20.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/3af69bef-edb3-f055-9523-1788b2071939.png)

![スクリーンショット 2023-05-20 14.21.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/a5f61adc-d7be-72c3-8edd-9e01d7b4ff8e.png)


ドメインは階層構造になっています。
実はurlはwww.examle.com.のように最後に.がついていて、この.がルートドメインに当たります。

ルートドメイン.→.com→expamle→wwwと降っていき、www.examle.comのwebサーバーを探します。

ちなみに、DNSサーバーは一度検索した結果を一定期間キャッシュに保存します。
そのため、一度接続したドメインには素早く接続することが可能です。

### プロトコルスタック
![スクリーンショット 2023-05-20 14.27.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/648481b7-45be-d6e6-9e3b-89a2a4706d67.png)

上記にも記載したようにブラウザは実際にメッセージを送信する機能を持っていないので、メッセージ送信はOS内部のプロトコルスタックが行います。

サーバーとクライアント間でソケットを繋いでデータを送受信します。

このソケット同士を接続する際に、ソケットを識別するために使用するのが**ディスクリプタ**というものになります

## TCP/IP
![スクリーンショット 2023-05-20 14.37.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/5679a42a-60cf-2e27-c161-5c95f3826e21.png)

データを送信する際にソケットは
作成
接続→connect
送受信→read,write
切断→close
抹消

という工程があります。

### TCPプロトコル

データの送受信にはTCPとUDPという二つのプロトコルがあります。

TCPはデータが正しく相手側に送信されたかACK番号によって確認します。

そのためTCPではデータの送信に信頼性がありますが、転送速度は低速になってしまいます。

### パケット
![スクリーンショット 2023-05-20 14.49.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/9e39ac42-6b51-6b38-b27c-859fc0138dbe.png)


データは小さい小包のような形としてパケットという単位に分けて送信されます。
パケットの中身はヘッダーとデータです。
ヘッダーにはどこにパケットが送られるかという情報があり、データ部分には実際に送信されるデータがあります。

### UDPプロトコル
UDPでは接続のフェーズがありません。
パケットは送信のみで、TCPのように送ったパケットの状態を監視することはないので、データが抜け落ちる可能性があります。

UDPでは高速なデータの送信ができるので、音声や動画データの送信に向いています。

https://hldc.co.jp/blog/2019/07/11/2819/

ハブ、ルーターの章は今回省略

## アクセス回線
![スクリーンショット 2023-05-20 15.18.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/431a8a6c-2cc9-96ec-6f7b-bb4d4568b442.png)

アクセス回線というのはインターネットと家庭や会社のLANを結ぶ通信回線のこと。

インターネットも家庭のLANと同じ仕組みです。
単純に規模が大きくなっただけ

アクセス回線にはADSL,FTTH,CATV,電話回線などがある

### ADSL
ADSLモデムがパケットをセルに分割し、電気信号に変えて送信します。

この信号は電話回線を使って渡されます。
電話からの電気信号なのか、ADSLの電気信号なのかはスプリッタが判断して分けます。

そうして信号が電話局に送られます。

### 光ファイバ(FTTH)
光ファイバでは電気信号ではなく、光の信号を流してデジタルデータを伝えます。

電気と光の速度はほとんど変わりませんが、電気信号は周波数が高くなるほど、伝送損失が大きくなります。

しかし、光信号では伝送損失が少ないため、高速で安定したデータの送信が可能になります。

## webサーバー
webサーバーにはパケットを送信しますが、その前にファイアウォールを通過する必要があります。

ファイアウォールは特定のパケットのみをwebサーバーに通します。

その方式はパケット・フィルタリング型が主流です。

パケットフィルタリングでは、パケットのヘッダー情報を使って判断します。

しかし、ファイアウォールではパケットの中身までは見れないので、パケットに有害なデータが含まれていた場合攻撃されてしまいます。

### 負荷分散
・DNSサーバーに複数のサーバーを対応づけるラウンドロビン方式

例えば

www.example.com

というサーバー名に対して

192.0.2.60
192.0.2.70
192.0.2.80

という３つのIPアドレスを対応づけると、最初の問い合わせには

192.0.2.60 192.0.2.70 192.0.2.80

と３つ並べて回答し、次の回答には

192.0.2.70 192.0.2.80 192.0.2.60

と並び替えて回答していくので、複数サーバーにアクセスを分散されることが可能です。

**欠点**
・webサーバーが故障していてもそのwebサーバーに振り分けてしまう
・複数のページにまたがってやり取りする場合、やり取り履歴が消えてしまう。

### ロードバランサー
![スクリーンショット 2023-05-20 15.56.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/a8bfacb5-287a-7540-5496-ed90d1dd2ab7.png)

上記の不具合を解決するために、ロードバランサーがある。

まず、ロードバランサーをwebサーバーの代わりにDNSサーバーに登録します。
 
そうするとクライアントはロードバランサーにリクエストを送り、ロードバランサーが適切なwebサーバーにリクエストを送信します。

これにより、複数ページに跨った場合も同じwebサーバーとやり取りでき、安定したデータの送受信が可能になります。

### キャッシュサーバー
![スクリーンショット 2023-05-20 16.05.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/f4e0fb62-df1f-b4ce-c8ab-47b02f84fac5.png)


webサーバーを複数台並べるのではなく。データベースサーバーとwebサーバーというふうに役割に応じてサーバーを分ける方法のこと。

キャッシュサーバーは**プロキシ**という仕組みを使って、データをキャッシュするサーバー。

プロキシとはwebサーバーとクライアントの間に入ってWebサーバーへのアクセス動作を仲介する役割を持ったもの。
また、Webサーバーから受け取ったデータをディスクに保存しておき、そのデータをWebサーバーに変わってクライアントに送り返す機能を持っています。

これをキャッシュと呼び、キャッシュサーバーはこの機能を利用します。

キャッシュサーバーはWebサーバーから受け取って保存しておいたデータを読み出してクライアントに送信するだけなので、Webサーバーより素早くデータを送信することができる。

クライアント側にキャッシュサーバーを置く方法もある。
→インターネットへのトラフィックを減らせるので効率はいいが設定が大変。

そうして生まれたのがCDNです。

### CDN(コンテンツ配信サービス)
インターネット全体にキャッシューサーバを配置し、クライアント側に近い場所のキャッシュサーバーにアクセスさせるサービスのこと。
これを使えば、トラフィックを減らしつつwebサーバー側がキャッシュサーバーをコントロールできる。

CDNを使う場合、インターネット全体に設置されたキャッシュサーバーから最寄りのキャッシュサーバーを見つける必要があります。

その方法の一つがHTTPヘッダーのLocationを使用する方法です。

Locationが近いキャッシュサーバーにリダイレクトさせることで、最寄りのキャッシュサーバーを設定できる

## webサーバー
webサーバーはクライアント側から複数のリクエストが送られてくるため、１対多の対応が必要です。

そのため、クライアントとの接続を待ち受ける部分とやり取りする部分に分かれています。

また、それぞれのクライアントごとに1対1の対応をするためにはマルチスレッドと呼ばれる機能により、多数のプログラムを同時並列実行できます。

webサーバーはクライアント側から送られたHTTPリクエストに則ってHTTPレスポンスを返します。

## ブラウザがHTTPレスポンスを受け取る

まず、レスポンスメッセージのヘッダーフィールドにあるContet-Typeでデータの種類を判断します。

例
ContentType:text/html; charset=utf-8

ちなみにHTTPレスポンスはタイプごとに送信するので、text.html以外にも
image, video, messageなど様々存在します。

最後にブラウザが受け取ったデータを表示して終了です。

## まとめと感想

再度流れをまとめると

1.urlをDNSサーバーに問い合わせ、IPアドレスを取得する
2.IPアドレスからwebサーバーを特定し、HTTPリクエストを送信する
3.webサーバーはHTTPリクエストを読み取り、HTTPレスポンスを返す
4.ブラウザが受け取ったHTTPレスポンスから画面を表示する

この間にロードバランサーがあったり、キャッシュサーバーになったりと色々細かい部分がありますが、基本的な流れは上記になると理解しています。

根本的な仕組みを理解することで、どこでエラーが発生しているのか？
パフォーマンスの最適化などが可能になると感じました。

CDNを使うとなぜ画像の表示が早くなるのか、キャッシュサーバーとは？プロキシとは？など、自分の理解が浅かった部分がしっかり理解できたので、本書はすごく役に立つものだなと感じます。

また、学習は反復することで身に付くのでこれからもちょくちょく見返して理解を深めようと思います。

もし参考になったらいいねやストックしていただけると嬉しいです。

twitterでwebのフロントエンドについて主に発信しているので、よかったらフォローしてください！

一緒に勉強していきましょう

twitter
https://twitter.com/js_manabitai


## 参考

https://zenn.dev/ak/articles/61d25099295372

https://zenn.dev/ak/articles/c28fa3a9ba7edb