Pythonのwebsocket-clientを使ってみた

記事タイトルとURLをコピーする

アプリケーションサービス部の鎌田(義)です。

PythonのWebSocketクライアント用ライブラリである、
websocket-client を使ってみたので、基本的な使用方法をご紹介します。

WebSocketとは

WebサーバとWebクライアント間で双方向に通信できるようにする技術です。
コネクションを維持し、サーバ側からもクライアントへデータを送信することができます。
チャットアプリケーションなどのリアルタイムで継続的にデータ交換が必要なサービスでよく利用されています。

サンプルチャットアプリケーションを構築

今回は、websocket-clientを使うことが目的なので、
サーバ側は以下のチュートリアル通りにさくっと構築します。

CloudFormationテンプレートが用意されているので、
テンプレートをダウンロードし、
CloudFormationコンソールからテンプレートを使用してスタックの作成を行います。

API Gateway (WebSocket API)は、手動での作成となっていますが手順通りに行えば5分ほどで作成できるかと思います。

docs.aws.amazon.com

websocket-clientを使ってみる

クライアント側は、websocket-client を使用します。

動作検証には、以下バージョンを使用しました。

  • Pythonバージョン: 3.11.4
  • websocket-clientバージョン: 1.8.0

先ほど構築したチャットアプリケーションにメッセージを送信するクライアント側のコードを準備します。
基本的には、ライブラリのREADME記載のコードをそのまま使用していますが以下2点変更を加えました。
on_openで、接続開始時にHello, Worldをサーバに送信します。
on_messageで、サーバから受信したメッセージをプロンプトに出力しつつ、受信メッセージをそのままオウム返しでサーバに送信しています。

websocket_client_test.py

import json
  
import websocket
  
url = "wss://<API_ID>.execute-api.ap-northeast-1.amazonaws.com/production"
  
  
def on_message(ws, message):
    print("received: ", message)
    r = {"action": "sendmessage", "message": f"bot> {message}"}
    ws.send(json.dumps(r))
  
  
def on_error(ws, error):
    print(error)
  
  
def on_close(ws, close_status_code, close_msg):
    print("### closed ###")
  
  
def on_open(ws):
    print("Opened connection")
    r = {"action": "sendmessage", "message": "bot> Hello, World"}
    ws.send(json.dumps(r))
  
  
if __name__ == "__main__":
    ws = websocket.WebSocketApp(
        url,
        on_open=on_open,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close,
    )
  
    ws.run_forever()

次にインタプリタを起動し、以下のように入力していきます。
インタプリタで起動している画面をクライアント①とします。
ws.recv()でサーバからデータを受信するのを待つ状態になります。

クライアント①

>>> import json
>>> import websocket
>>> url = "wss://<API_ID>.execute-api.ap-northeast-1.amazonaws.com/production"
>>> ws = websocket.create_connection(url)
>>> ws.recv()
  

もう一つターミナルを開き先ほど作成したPythonファイルを実行します。
こちらの画面をクライアント②とします。

クライアント②

$ python websocket_client_test.py
Opened connection

クライアント①の画面で、Hello, Worldがサーバから受信できました。
引き続きクライアント①の画面でメッセージ送信と受信確認をしてみます。

クライアント①

>>> import json
>>> import websocket
>>> url = "wss://<API_ID>.execute-api.ap-northeast-1.amazonaws.com/production"
>>> ws = websocket.create_connection(url)
>>> ws.recv()
'bot> Hello, World'
>>> ws.send(json.dumps({"action": "sendmessage", "message": "こんにちは"}))
76
>>> ws.recv()
'bot> こんにちは'
>>> ws.send(json.dumps({"action": "sendmessage", "message": "元気ですか?"}))
82
>>> ws.recv()
'bot> 元気ですか?'
>>> ws.send(json.dumps({"action": "sendmessage", "message": "さようなら"}))
76
>>> ws.recv()
'bot> さようなら'
>>> ws.close()

クライアント②の画面では、以下のように出力されています。
終了する場合は、Ctrl + Cで終了します。

クライアント②

$ python websocket_test.py 
Opened connection
received:  こんにちは
received:  元気ですか?
received:  さようなら

最後に

今回は基本的な機能のみを使用しました。
proxyの使用や、切断時の再接続など実運用の上で必要になってきそうな機能もある為、
引き続き分かったことがあればご紹介していきたいと思います。

最後までご覧いただきありがとうございました。

鎌田 義章 (執筆記事一覧)

2023年4月入社 AS部DS3課