6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

python で socket受信を多重化する(サンプルプログラム)

Posted at

はじめに

以前書いた記事 が、1リクエストずつしか処理できない形になっていたので、マルチスレッド化して多重化(同時処理)できるようにしたサンプルプログラム。
backlog(ドキュメント読んだ限りでは受信可能数)という引数設定があったため、勝手にやってくれるのかと勘違い…。

環境

  • windows10 pro
  • wsl2(20.04.5 LTS (Focal Fossa))
  • Dockerのバージョン
    • Docker version 20.10.18, build b40c2f6
    • docker-compose version 1.29.2, build 5becea4c
      ※Docker Desktop ではありません
      ※通信のリクエストは、Windowsからも行っています
  • python 3.10.7
  • コンテナのポート設定については
ports: 
  - 50000:50000

 を入れています

コード

receive.py
import socket
from concurrent.futures import ThreadPoolExecutor
import time

# 受信IP
RCV_HOST = "0.0.0.0"
# 受信ポート
RCV_PORT = 50000
# 受信可能数(指定以上超えると、待ちが発生せずに処理終了??)
BACKLOG = 10
# 一度の通信受信できる最大データバイト数
BUFSIZE = 1024
# 最大同時処理数
MAXWORKER = 10


# 受信~返信処理
def data_comminicate(conn):
    while True:
        try:
            # 通信を受信
            rcv_msg = conn.recv(BUFSIZE)
            # 内容がないときは、処理をしない
            if not rcv_msg:
                break
            # 受信内容の確認
            print("rcv_msg:", rcv_msg)

            # 多重化しているかの確認(ここに受信データを使った処理を記載)
            print("before sleep:", rcv_msg)
            time.sleep(10)
            print("after sleep:", rcv_msg)

            # 返信処理
            conn.send(b":Received - " + rcv_msg)

        except Exception as e:
            break
        finally:
            conn.close()


if __name__ == "__main__":
    try:
        # ソケット定義
        sct = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 再使用設定(3つ目の引数は違う可能性あり)
        sct.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, BACKLOG)
        # 受信設定
        sct.bind((RCV_HOST, RCV_PORT))
        sct.listen(BACKLOG)

        # マルチプロセスで実行
        with ThreadPoolExecutor(MAXWORKER) as executor:
            # 継続受信のため、ループ
            while True:
                try:
                    # コネクション定義(切断処理の判定対策)
                    conn = None
                    # 受信の待機
                    (conn, addr) = sct.accept()
                    # マルチプロセスで データ受信~返信を実行
                    executor.submit(data_comminicate, conn)
                except KeyboardInterrupt as e:
                    # キーボード(ctrl+c等)で抜けたとき
                    print("KeyboardInterrupt", e)
                finally:
                    # 受信せずに終わる場合(ctrl+c等)は、処理を抜けさせる
                    if conn is None:
                        break

    except Exception as e:
        # socketオブジェクトの定義ミス
        print("socket variable error", e)
    finally:
        # socketオブジェクト終了
        sct.close()

最後に

あまり自分の意向に沿った記事が見つけられなかったため、bingAI チャットで concurrent.futures の ThreadPoolExecutor を使った socketの多重化サンプルプログラムが欲しい みたいなキーワードで生成させると、かなり意向に沿った感じのサンプルを作成してくれました。
threadpoolexecutor で…とするとpythonのデフォルトパッケージではなく、threadingでやると…というような回答が来ましたので、調整は面倒ですが、なかなか面白くもあるなと思った次第です。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?