1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TCP/IP の通信待ちのサーバーで、毎日、決まった時刻になったら他のタスクを実行するサンプル

Last updated at Posted at 2024-10-29

開発を行った動機

AI で Web 上に検索結果を表示するシステム、index.html から client.php に検索要求を送信し、client.php が TCP/IP 通信で python のサーバー server.py に検索要求を伝えるというシステムを作っていました。検索サーバーは、検索の元ネタファイルを読み込んで、検索要求を待っています。元ネタファイルを読み込むのに5分以上かかるので、この index.html, client.php, server.py という配置にしました。どういうことかというと、server.py は一度元ネタファイルを5分かけて読み込んで、あとは通信で検索要求を待っていれば、タイムラグなく検索要求に答えられるからです。検索の元ネタのファイルは、別のプログラムで毎晩24時に更新されます。すると、通常は、検索要求を待っている server.py は、24時になったことを検出できなければなりません。通常の TCP/IP のネットワークサーバーでは、


socket→bind→listen → 
     while True → accept→ recv → send → close →
     ↑                                         ↓
     ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←

のようなループの accept で通信待ちでブロックされ、ほかのタスクを実行することはありません。これは困りました。毎晩24時になったことを検出し、検索元ネタファイルを読み込みなおさなければなりません。上のダイヤグラムだと、読み込みなおしの入る余地がありません。

解決策

ちゃんと、解決策が用意されていました。それは、accept について、timeout を設定して一定時間で例外を発生させ、例外が発生したら他のタスクを実行する。というものです。

サンプルプログラム

import socket
import datetime

def main():

    # ss = SemanticSearch() 検索用クラスのインスタンスの初期化
    # ss.load_corpus( filename ) 検索元ネタファイルを読み込む
                
    # ソケットのパラメーター定義
    server_ip = "127.0.0.1"
    server_port = 10000
    listen_num = 10
    buffer_size = 8192

    # 1.ソケットオブジェクトの作成
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.作成したソケットオブジェクトにIPアドレスとポートを紐づける
    tcp_server.bind((server_ip, server_port))
    tcp_server.settimeout( 1.0 )

    # 3.作成したオブジェクトを接続可能状態にする
    tcp_server.listen(listen_num)

    # 4.ループして接続を待ち続ける
    while True:
        try:
            # 5.クライアントと接続する
            client,address = tcp_server.accept()
            # 6.データを受信する
            data = client.recv(buffer_size)
            data = data.decode('UTF-8')
            print("[*] Received Data : {}\n".format(data)) # data は検索文。

            #検索実行
            #send_result = ss.search( data )
            # 7. 返事を返す。
            client.send( send_result.encode( "UTF-8" ) )

            # 8.接続を終了させる
            client.close()

        except socket.timeout as e:
            t_now = datetime.datetime.now().time()
            if '00:00' ==  str( t_now )[:5]:
                tcp_server.close()
                
                #ここで検索の元ネタファイルを読み直す。10分とかかかる。その間、通信はお断り。
                # ss = SemanticSearch() 検索用クラスのインスタンスの初期化
                # ss.load_corpus( filename ) 検索元ネタファイルを読み込む

                # 1.ソケットオブジェクトの作成
                tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

                # 2.作成したソケットオブジェクトにIPアドレスとポートを紐づける
                tcp_server.bind((server_ip, server_port))
                tcp_server.settimeout( 1.0 )

                # 3.作成したオブジェクトを接続可能状態にする
                tcp_server.listen(listen_num)

目標達成

目標は検索元ネタファイルの更新です。

#ここで検索の元ネタファイルを読み直す。10分とかかかる。その間、通信はお断り。
# ss = SemanticSearch() 検索用クラスのインスタンスの初期化
# ss.load_corpus( filename ) 検索元ネタファイルを読み込む

ここで更新しています。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?