Back to Blog

PythonでWebフレームワークを使わずにWebサイトを作成する方法【Webの仕組みを利用しよう!】

Python

2024年8月23日

こんにちは!

今回の記事では、PythonでWebフレームワークを使わずにWEbサイトを作成する方法について解説します。

Pythonには、DjangoやFlaskといった様々なWebフレームワークがあります。Webフレームワークを使うことで、簡単にWebサイトを作成することが可能です。

しかし、今回はあえてWebフレームワークを使用しません。Webフレームワークを使わないことで、Webサイトをどのように作成できるのか、低レイヤー部分を理解することが可能になります。

Webの仕組みをくわしく知りたい方は是非お読みください!

Webの基本的な仕組み

PythonでWebサイトを作成する前に、基本的なWebの仕組みについておさらいしましょう。

クライアントとサーバ

Webはクライアントとサーバの通信によって成り立っています。

クライアント(通常はWebブラウザ)は、ユーザーが指定したURLに基づいてサーバにリクエストを送信します。

サーバはそのリクエストを受け取り、適切なレスポンス(HTMLページ)をクライアントに返します。

この通信は主にHTTP(Hypertext Transfer Protocol)というプロトコルに基づいて行われます。HTTPは、クライアントがサーバにリソースをリクエストし、サーバがそのリソースを提供するためのルールを定めたものです。

HTTPリクエストとレスポンス

次にクライアントとサーバーの通信の中身を見てみましょう。

HTTPリクエストは、クライアントがサーバに対して行う要求です。リクエストは通常、以下のような形式を取ります。

GET / HTTP/1.1
Host: localhost:8000

GETはリクエストのメソッドです。これは、サーバからデータを取得することを意味します。
/はリクエストするリソースのパスを示しています。この例では、ホームページをリクエストしています。HTTP/1.1は使用するHTTPプロトコルのバージョンです。

サーバはこのリクエストを受け取り、以下のようなHTTPレスポンスを返します。

HTTP/1.1 200 OK
Content-Type: text/html

<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>

HTTP/1.1 200 OKは、リクエストが成功したことを示すステータスラインです。
Content-Type: text/htmlは、レスポンスの内容がHTMLであることを示すヘッダーです。
空行の後に続く部分が実際のレスポンスボディであり、クライアントに表示されるコンテンツです。

このようなやりとりを行いWebページを表示しています。

socketモジュールを使用してWebサーバを構築する

次に、これらの基本的な仕組みを理解した上で、socketモジュールを使用して実際にHTTPサーバを構築してみましょう。

Pythonには、http.serverというライブラリがありますが、socketモジュールを使うことで、先ほど説明したような低レイヤーの仕組みを理解することが可能です。

ソケット(socket)とは?

まずは、今回使用するソケットについて簡単に説明します。

ソケット(socket)は、ネットワーク通信においてデータの送受信を行うためのエンドポイントのことです。

具体的には、ソケットは通信を行うための一種のインターフェースであり、IPアドレスとポート番号を組み合わせて、ネットワーク上の特定のプロセス(アプリケーション)を識別します。

シンプルなWebサーバの実装

ここでは、シンプルなWebサーバーを作成します。Webページへアクセスすると、「Hello, World!」と表示するサイトです。

以下のコードを記述したpythonファイルを作成しましょう。ファイル名はhttp_server.pyとします。

import socket

HOST, PORT = '', 8000

# ソケットを作成
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.bind((HOST, PORT))  # ホスト名とポート番号を指定
listen_socket.listen(1)  # 最大接続数を指定

print(f"サーバを起動しました。http://localhost:{PORT} でアクセスできます。")

while True:
    client_connection, client_address = listen_socket.accept()  # クライアントからの接続を待つ
    request = client_connection.recv(1024).decode('utf-8')  # クライアントからのリクエストを受信
    print(request)

    # HTTPレスポンスを作成
    http_response = """\
HTTP/1.1 200 OK

<html><body><h1>Hello, World!</h1></body></html>
"""
    client_connection.sendall(http_response.encode('utf-8'))  # レスポンスをクライアントに送信
    client_connection.close()  # 接続を閉じる

コードの解説は後ほど行います。

Webサーバーの起動

続いて、先ほど作成したpythonファイルからWebサーバーを起動してみます。

以下のコマンドを実行してみましょう。

python http_server.py

コマンドを実行すると、「サーバを起動しました。http://localhost:8000 でアクセスできます。」というメッセージが表示します。

PythonでWebサーバーの起動

この状態で、ブラウザからhttp://localhost:8000へアクセスしてみましょう。

以下のように「Hello, World!」と表示されたら成功です。

Webページの表示

このように、Webフレームワークを使わなくても、Webサーバーとして起動することができました。

ソースコードの解説

次に、http_server.pyファイルのコードを解説します。

このコードを理解することで、Webサーバーがどのような仕組みで動作しているのかがわかります。

インポート

まず1行目

import socket

ここでは、ネットワーク通信を行うための標準ライブラリであるsocketモジュールをインポートしています。socketモジュールを使用することで、Pythonでソケット通信(TCP/IP通信)を行うことができます。

ホストとポートの設定

続いて、3行目

HOST, PORT = '', 8000

HOSTはサーバがバインドするホスト名を指定します。空文字列(”)は、全ての利用可能なネットワークインターフェース(ローカルホストを含む)にバインドすることを意味します。
PORTはサーバがリクエストを受け付けるポート番号を指定します。今回は、8000番ポートを使用します。

ソケットの作成と設定

続いて6~8行目では、ソケットの作成と設定を行なっています。

listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

socket.socket()は、新しいソケットオブジェクトを作成します。
socket.AF_INETは、IPv4アドレスファミリを指定します。つまり、IPv4プロトコルを使用して通信を行うことを意味します。
socket.SOCK_STREAMは、TCPプロトコルを指定します。TCPは信頼性の高い接続指向のプロトコルで、データの順序や誤りの検出を保証します。

listen_socket.bind((HOST, PORT))

bind()メソッドは、ソケットを特定のホスト名とポート番号にバインドします。3行目で設定したHOSTとPORTの値を使って、サーバがリクエストを受け取るアドレスとポートを設定します。

listen_socket.listen(1)

listen()メソッドは、ソケットをサーバモードにして、クライアントからの接続を待ち受けます。引数1は、同時に待ち受けられる接続の最大数を指定しています。今回は、同時に1つの接続のみを受け付けます。

サーバの起動メッセージ

続いて、10行目

print(f"サーバを起動しました。http://localhost:{PORT} でアクセスできます。")

print()関数で、サーバが起動し、指定されたポート(この場合は8000)でアクセス可能であることをユーザーに通知します。

クライアント接続の処理ループ

続いて、12~24行目は、クライアント接続の処理ループを行い、常にクライアントからのWeb通信を受信できるようにします。

while True:

while True:で無限ループを開始します。これにより、サーバは常にクライアントからの接続を受け付けるようになります。

  client_connection, client_address = listen_socket.accept()

accept()メソッドは、クライアントからの接続要求を受け入れます。このメソッドはブロッキングメソッドで、クライアントが接続してくるまで処理が止まります。
client_connectionにはクライアントとの通信に使用するソケットオブジェクトが、client_addressには接続してきたクライアントのアドレスが格納されます。

  request = client_connection.recv(1024).decode('utf-8')

recv()メソッドを使用して、クライアントから送信されたデータを受信します。1024は受信するデータの最大バイト数を指定しています。
decode(‘utf-8’)は、バイトデータをUTF-8エンコーディングでデコードし、人間が読める文字列に変換します。

  print(request)

printで受信したリクエストをコンソールに出力します。これはHTTPリクエストの内容が表示されます。

HTTPレスポンスの作成と送信

ループ内の18行目では、レスポンスを生成しています。

  http_response = """\
    HTTP/1.1 200 OK

    <html><body><h1>Hello, World!</h1></body></html>
  """

http_response変数には、サーバからクライアントに返すHTTPレスポンスの内容が格納されています。
このレスポンスは、HTTP/1.1 200 OKというステータスラインを持ち、クライアントにリクエストが正常に処理されたことを示します。
レスポンスのボディ部分には、HTMLで記述された「Hello, World!」というメッセージが含まれています。

19行目では、レスポンスをクライアントに送信します。

  client_connection.sendall(http_response.encode('utf-8'))

sendall()メソッドは、レスポンスデータをクライアントに送信します。encode(‘utf-8’)を使って文字列をバイトデータにエンコードしています。

最後に、最後に、close()メソッドを使用してクライアントとの接続を閉じます。

client_connection.close()

これにより、サーバは新たなクライアント接続を受け付ける準備が整います。

このようなsocketの動きでWebサーバーの処理を実装しています。

まとめ

今回の記事では、pythonで非常にシンプルなHTTPサーバを構築しました。

サーバは、クライアント(通常はWebブラウザ)からの接続を受け付け、リクエストを処理して簡単なHTMLレスポンスを返すという基本的な機能を持っています。

PythonでWebフレームワークを使わないことで、Webの基本的な仕組みを理解し、TCP/IPやHTTPプロトコルの基本を学ぶことができました。

このように1からWebサーバーを実装することで、知識が深掘りできたと思います。

今回の記事が何かのお役になれば幸いです。

ここまでお読みいただきありがとうございました。

             

Pythonの基礎から応用まで学べる
Python WebAcademy

Python WebAcademyでは、Pythonの基礎からアーキテクチャなどの応用的な内容まで幅広く学べます。また、ブラウザ上で直接Pythonコードを試すことができ、実践的なスキルを身につけることが可能です。

             Pythonの学習を始める