【プログラミング】Pythonにてクライアント~サーバ間のソケット通信を行う

Python

今回は、Pythonにてクライアント~サーバ間のソケット通信を行う方法を掲載します。

1.サーバ側のサンプルコード

サーバは、クライアントからの接続を受け入れ、データを受信し、応答を返す役割を担います。
以下のコードは、サーバ側のサンプルコードです。

import socket

def start_server(host='127.0.0.1', port=65432):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
        server_socket.bind((host, port))
        server_socket.listen()

        print(f'Server listening on {host}:{port}')

        # 接続待ち
        conn, addr = server_socket.accept()
        with conn:
            print(f'Connected by {addr}')
            
            # タイムアウト設定 (秒)
            conn.settimeout(10.0)
            
            try:
                while True:
                    data = conn.recv(1024)
                    if not data:
                        break
                    print(f'Received: {data.decode()}')
                    
                    # 受け取ったデータに対して応答
                    response = f'ACK: {data.decode()}'
                    conn.sendall(response.encode())
            except socket.timeout:
                print('Connection timed out')

if __name__ == "__main__":
    start_server()

IPアドレス”127.0.0.1″は、localhostを意味します。
クライアント側のプログラムも同様の設定とすることで、1台のPC上でサーバ/クライアントの処理を実行可能です。

上記サンプルでは、サーバ側マシンの待ち受け用ポート(サンプルでは’65432’)に向けたデータが送信されるまで待ち状態となり、送信を検知した場合、データを受信後、その応答を返しています。
具体的には、
・socket:ソケット生成
・bind:ソケット登録
・listen:ソケット接続準備
・accept:ソケット接続待機

このような流れで送信データの待ち受けを行い、データ送信が確認できたら、”recv”でデータを受信するという流れです。

なお、タイムアウト値を設定(サンプルでは10秒)していますので、その時間内に送信されないと、タイムアウトエラーとなります。
※ポート番号、タイムアウト値等は、適宜変更してください。

2.クライアント側のサンプルコード

クライアントは、サーバーに接続してデータを送信し、応答を受け取る役割を担います。
以下のコードは、クライアント側のサンプルコードです。

import socket

def start_client(host='127.0.0.1', port=65432):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
        client_socket.connect((host, port))
        
        # タイムアウト設定 (秒)
        client_socket.settimeout(10.0)
        
        try:
            message = 'Hello, Server!'
            print(f'Sending: {message}')
            client_socket.sendall(message.encode())
            
            # サーバーからの応答を受け取る
            data = client_socket.recv(1024)
            print(f'Received: {data.decode()}')
        except socket.timeout:
            print('Connection timed out')

if __name__ == "__main__":
    start_client()

サーバ側マシンの待ち受け用ポート(サンプルでは’65432’)に向けて”Hello, Server!”というテキストデータを送信します。
まずは”connect”にてサーバへの接続要求を行い、正常応答があった場合、”sendall”にてデータ送信を行うという流れとなります。
送信が成功すると、サーバ側からデータ送信に対する応答が更に返信されますので、それを受け取り、通信を終了します。

こちらもサーバ側と同様、タイムアウト値を設定(サンプルでは10秒)しており、その時間内にサーバ側に接続されないと、タイムアウトエラーとなります。
※ポート番号、タイムアウト値等は、適宜変更してください。

3.実行結果

実行手順としては、まずサーバ側のプログラムを実行しておきます。
すると、acceptの箇所でクライアントからの接続待ちとなり、

Server listening on 127.0.0.1:65432

上記メッセージがコンソール上に出力されます。
この状態で、クライアント側のプログラムを実行してみて下さい。

Sending: Hello, Server!
Received: ACK: Hello, Server!

このようなメッセージがコンソール上に表示されるはずです。
サーバ側への送信(send)が正常に動作し、その後のサーバ側からの返信も検知できています。


クライアント側のプログラムを実行した後のサーバ側のコンソール結果についても、最終的には

Server listening on 127.0.0.1:65433
Connected by ('127.0.0.1', 55092)
Received: Hello, Server!

このような形となり、クライアントからのデータ受信が正常に動作したことが確認できます。

まとめ

今回は、Pythonにてクライアント/サーバ間のソケット通信を行ってみました。
上記サンプルは簡単な例となりますので、実際に運用する際にはエラーハンドリング等がもう少し複雑になるかと思います。
ただ、基本的にはこの形をベースとして実装できると思いますので、是非
参考にしてください。
(今回はここまで)

お読みいただき、有難うございました!

コメント

タイトルとURLをコピーしました