以下の内容はhttps://pydocument.hatenablog.com/entry/2023/04/25/001934より取得しました。


Python `socket` モジュールによるネットワークプログラミング

Pythonは、ネットワークプログラミングを行うためのsocketモジュールを提供しています。この記事では、socketモジュールを使用してTCP/IPおよびUDPソケットを介した基本的なクライアント/サーバー通信を実装する方法を、具体的なコード例とともに解説します。

ソケットとは

ソケットは、ネットワーク通信のエンドポイントです。プロセス間通信(IPC)の一種で、異なるコンピュータ上のプロセス間、または同一コンピュータ内の異なるプロセス間でデータを送受信するために使用されます。ソケットには主に以下の2つのタイプがあります。

  • TCP (Transmission Control Protocol): 信頼性の高い、接続指向のプロトコルです。データの順序と到達性が保証されます。Webブラウジング、メール送信など、データの正確性が重要なアプリケーションで使用されます。
  • UDP (User Datagram Protocol): 信頼性の低い、コネクションレス型のプロトコルです。データの順序や到達性は保証されませんが、TCPに比べてオーバーヘッドが少なく、高速な通信が可能です。オンラインゲーム、ビデオストリーミングなど、多少のデータ損失が許容されるリアルタイムアプリケーションで使用されます。

TCPソケットプログラミング

TCPソケットは、信頼性の高い双方向通信を提供します。以下の例では、PythonでシンプルなTCPサーバーとクライアントを作成する方法を示します。

TCPサーバーの実装

TCPサーバーを実装し、クライアントからの接続を待ち受け、受信したデータをそのままエコーバック(送り返す)します。

import socket

HOST = '127.0.0.1'  # ローカルホスト
PORT = 65432        # 使用されていないポート番号

# AF_INET: IPv4, SOCK_STREAM: TCP
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # ポートを再利用可能にする (TIME_WAIT状態のポートをすぐに再利用)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        s.bind((HOST, PORT))  # ソケットにアドレスをバインド
    except OSError as e:
        print(f"Error binding to port {PORT}: {e}")
        exit(1)

    s.listen()  # クライアントからの接続を待機
    print(f"Listening on {HOST}:{PORT}")

    conn, addr = s.accept()  # クライアントからの接続を受け入れる
    with conn:
        print('Connected by', addr)
        while True:
            try:
                data = conn.recv(1024)  # クライアントからデータを受信
                if not data:
                    break  # データがなければ接続終了
                print(f"Received: {data.decode()}")
                conn.sendall(data)  # 受信したデータをそのままクライアントに送り返す (エコー)
            except ConnectionResetError:
                print("Client disconnected unexpectedly")
                break
            except Exception as e:
                 print(f"An error occurred: {e}")
                 break

クライアントからの接続を待ち受けるため、socket.socket(socket.AF_INET, socket.SOCK_STREAM)TCPソケットを作成します。s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)は、サーバー停止後すぐにポートを再利用できるようにするための設定です。

s.bind((HOST, PORT))でソケットを特定のアドレスとポートにバインドし、s.listen()で接続要求の受付を開始します。s.accept()でクライアントからの接続を確立し、新しいソケットオブジェクト(conn)を取得します。これで、conn.recv(1024)でクライアントからデータを受信し、conn.sendall(data)でそのデータをそのままクライアントに送り返すエコーサーバーとして動作します。

TCPクライアントの実装

上記のTCPサーバーに接続し、文字列を送信して、サーバーからの応答(エコー)を受信・表示します。

import socket

HOST = '127.0.0.1'  # サーバーのホスト名またはIPアドレス
PORT = 65432        # サーバーが使用しているポート番号

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    try:
        s.connect((HOST, PORT))  # サーバーに接続
    except ConnectionRefusedError:
        print(f"Connection refused. Ensure the server is running on {HOST}:{PORT}.")
        exit(1)

    s.sendall(b'Hello, server')  # サーバーにデータを送信
    data = s.recv(1024)  # サーバーからデータを受信

print('Received', repr(data.decode()))

socket.socket(socket.AF_INET, socket.SOCK_STREAM)TCPソケットを作成し、s.connect((HOST, PORT))でサーバーに接続を試みます。接続後、s.sendall(b'Hello, server')でサーバーにデータを送信し、s.recv(1024)でサーバーからの応答を受信、表示します。

UDPソケットプログラミング

UDPコネクションレスプロトコルです。TCPに比べて軽量ですが、信頼性は保証されません。

UDPサーバーの実装

UDPサーバーを実装し、クライアントからデータを受信し、受信したデータを大文字に変換してクライアントに送り返します。

import socket

HOST = '127.0.0.1'
PORT = 65432

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        s.bind((HOST, PORT))
    except OSError as e:
        print(f"Error binding to port {PORT}: {e}")
        exit(1)
    print(f"Listening on {HOST}:{PORT}")

    while True:
        try:
            data, addr = s.recvfrom(1024)  # クライアントからデータとアドレスを受信
            print(f"Received: {data.decode()} from {addr}")
            s.sendto(data.upper(), addr)  # 受信データを大文字にしてクライアントに送り返す
        except Exception as e:
            print(f"An error occurred: {e}")
            break

socket.socket(socket.AF_INET, socket.SOCK_DGRAM)UDPソケットを作成し、s.bind((HOST, PORT))で指定のIPアドレスとポートにバインドします。UDPコネクションレス型なので、TCPlisten()accept()は不要です。

s.recvfrom(1024)でクライアントからのデータと送信元アドレスを受信し、s.sendto(data.upper(), addr)で受信データを大文字に変換して送信元に返します。

UDPクライアントの実装

上記のUDPサーバーにデータを送信し、サーバーからの応答(大文字に変換されたデータ)を受信・表示します。

import socket

HOST = '127.0.0.1'
PORT = 65432

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    try:
        s.sendto(b'Hello, server', (HOST, PORT))  # サーバーにデータを送信
        data, addr = s.recvfrom(1024)  # サーバーからデータとアドレスを受信
        print(f"Received: {data.decode()} from {addr}")
    except Exception as e:
        print(f"An error occurred: {e}")

socket.socket(socket.AF_INET, socket.SOCK_DGRAM)UDPソケットを作成し、s.sendto(b'Hello, server', (HOST, PORT))でサーバーにデータを送信します。その後、s.recvfrom(1024)でサーバーからの応答と送信元アドレス(ここではサーバーのアドレス)を受信し、表示します。

応用: ノンブロッキングソケット

上記の例では、ソケット操作(recv, send, acceptなど)はブロッキングモードで行われます。つまり、これらの操作は完了するまでプログラムの実行をブロックします。大規模なアプリケーションでは、これはパフォーマンス上の問題を引き起こす可能性があります。

ノンブロッキングソケットを使用すると、ソケット操作がすぐに完了しない場合でも、プログラムの実行をブロックせずに他の処理を続行できます。ソケットをノンブロッキングモードに設定するには、setblocking(False)を呼び出します。ノンブロッキングソケットを使用する場合は、selectモジュールやasyncioライブラリなどを組み合わせて、ソケットの準備状態を効率的に監視する必要があります。実際には下記のように実装します。

# 例:ノンブロッキングソケットの設定 (TCPサーバーの一部)
s.setblocking(False)

ネットワーク自動化とプログラマビリティ 次世代ネットワークエンジニアのためのスキルセット [ Jason Edelman ]

まとめ

この記事では、Pythonsocketモジュールを使用してTCPおよびUDPソケットによる基本的なネットワーク通信を実装する方法を解説しました。ソケットプログラミングは、ネットワークに詳しい開発者にはなじみのあるテクノロジーですが、Pythonを使うことで、初心者でも簡単にネットワークプログラミングを始めることができます。これらのプログラムはPythonの基本的な文法とライブラリで実装することができます。Pythonの基礎学習には下記のようなサイトの利用が有効です。

[PR]

click.linksynergy.com

click.linksynergy.com




以上の内容はhttps://pydocument.hatenablog.com/entry/2023/04/25/001934より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14