ネットワークプログラミングは、インターネットやローカルネットワーク上でデバイス同士を通信させる技術です。Pythonには、このネットワーク通信を簡単に実現するためのsocketライブラリが標準で含まれています。このブログでは、socketライブラリを使ってクライアント/サーバーアプリケーションを作成する方法を、実際のコードを交えて紹介します。

クライアント/サーバーアーキテクチャとは?

ネットワークプログラミングにおける基本的な概念にクライアント/サーバーアーキテクチャがあります。このモデルでは、クライアントがリクエストを送り、サーバーがそのリクエストに応じて応答を返す形で通信が行われます。

  • クライアント:リクエストを送信する役割(例:ブラウザ、アプリケーション)
  • サーバー:クライアントからのリクエストに応じる役割(例:ウェブサーバー、データベースサーバー)

socketライブラリとは?

socketライブラリは、Pythonでネットワーク通信を行うための標準ライブラリです。socketを使うと、TCP(Transmission Control Protocol)やUDP(User Datagram Protocol)を使ったネットワーク通信が可能になります。一般的には、信頼性の高い通信を行うためにTCPが使用されますが、速度を重視する場合はUDPが使われます。

基本的なsocketの使用例

  • サーバー:クライアントからの接続を待ち、リクエストを処理します。
  • クライアント:サーバーに接続し、データを送信します。

Pythonでのサーバーの実装

まずは、Pythonで簡単なサーバーを作成します。サーバーは、指定されたIPアドレスとポートで待機し、クライアントからの接続を受け付けます。

import socket
# サーバーのホストとポートの設定
HOST = '127.0.0.1'  # ローカルホスト
PORT = 65432        # 通信に使用するポート
# ソケットの作成
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # ホストとポートにバインド
    s.bind((HOST, PORT))
    # 接続を待機
    s.listen()
    print('サーバーは待機中...')
    
    # クライアントからの接続を受け入れる
    conn, addr = s.accept()
    with conn:
        print(f'接続されました: {addr}')
        while True:
            # クライアントからデータを受信
            data = conn.recv(1024)
            if not data:
                break
            # クライアントに受信したデータをそのまま送信
            conn.sendall(data)

サーバーの動作解説

  1. ソケットの作成:socket.socket()を使ってサーバー側のソケットを作成します。AF_INETはIPv4アドレス、SOCK_STREAMはTCPプロトコルを指定しています。
  2. バインドとリッスン:bind()でサーバーのIPアドレスとポート番号を指定し、listen()で接続を待ちます。
  3. 接続の受け入れ:accept()でクライアントからの接続を受け入れ、通信が開始されます。
  4. データの受信と送信:recv()でクライアントから送信されたデータを受け取り、sendall()でそのデータをクライアントに送り返します。

Pythonでのクライアントの実装

次に、サーバーに接続してデータを送信するクライアントを作成します。

import socket
# サーバーのホストとポートの設定
HOST = '127.0.0.1'  # サーバーのIPアドレス
PORT = 65432        # サーバーのポート
# ソケットの作成
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # サーバーに接続
    s.connect((HOST, PORT))
    # メッセージを送信
    s.sendall(b'Hello, server!')
    # サーバーからのデータを受信
    data = s.recv(1024)
# 受信したデータを表示
print(f'サーバーからの応答: {data.decode()}')

クライアントの動作解説

  1. サーバーへの接続:socket.connect()を使って、指定されたホストとポートにあるサーバーに接続します。
  2. データの送信:sendall()を使ってサーバーにメッセージを送信します。メッセージはバイト列(b'...')として送信します。
  3. データの受信:recv()でサーバーからのデータを受信します。

クライアント/サーバーアプリケーションの実行

上記のサーバーとクライアントのコードをそれぞれ別々のターミナルで実行してみましょう。

サーバーを実行

python server.py

サーバーは、サーバーは待機中...というメッセージを表示してクライアントからの接続を待ちます。

クライアントを実行

別のターミナルで、次のコマンドを実行します。

python client.py

クライアントがサーバーに接続し、メッセージ「Hello, server!」を送信し、サーバーから同じメッセージを受け取るはずです。

サーバーからの応答: Hello, server!

サーバーの拡張:複数のクライアントを処理

上記のサーバー実装では、1つのクライアントしか同時に接続できませんが、スレッドを使うことで複数のクライアントに対応することが可能です。以下は、マルチクライアント対応のサーバーコードです。

マルチスレッドサーバーの実装

import socket
import threading
# クライアントごとに新しいスレッドで接続を処
def handle_client(conn, addr):
    print(f'接続されました: {addr}')
    with conn:
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)
# サーバーの設定
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    print('サーバーは待機中...')
    
    while True:
        conn, addr = s.accept()
        # 新しいクライアントごとにスレッドを起動
        client_thread = threading.Thread(target=handle_client, args=(conn, addr))
        client_thread.start()

このコードでは、新しいクライアントが接続されるたびにスレッドを作成し、並行してクライアントを処理します。これにより、複数のクライアントが同時にサーバーに接続できるようになります。

応用例:チャットアプリケーションの構築

クライアント/サーバーアーキテクチャをさらに発展させて、シンプルなチャットアプリケーションを作成することも可能です。クライアントがサーバーにメッセージを送り、サーバーが全クライアントにそのメッセージをブロードキャストする仕組みを作れば、リアルタイムのチャットシステムを構築できます。

まとめ

Pythonのsocketライブラリを使うことで、簡単にクライアント/サーバーアプリケーションを作成できます。今回は、基本的な通信の流れからマルチスレッドによるマルチクライアント対応までを解説しました。この技術を応用すれば、チャットアプリやファイル転送システムなど、さまざまなネットワークアプリケーションを開発することが可能です。Pythonでネットワークプログラミングを学び、さらに高度なアプリケーションに挑戦してみてください。