Open1

class ChatServerProtocol(asyncio.DatagramProtocol):

pdfpdf
class ChatServerProtocol(asyncio.DatagramProtocol):  # UDP用の非同期プロトコルクラス
    def __init__(self):
        self.transport = None  # UDPソケットの送受信用オブジェクト

    def connection_made(self, transport):
        self.transport = transport  # サーバーソケットが作成されたときに呼ばれる

    def datagram_received(self, data, addr):
        if not data:
            return  # データが空なら何もしない
        usernamelen = data[0]  # 最初の1バイトはユーザー名の長さ
        username = data[1:1+usernamelen].decode('utf-8')  # ユーザー名部分をデコード
        message = data[1+usernamelen:].decode('utf-8')    # 残りがメッセージ本文
        print(f"Received from {username}@{addr}: {message}")  # 受信内容を表示
        clients[addr] = time.time()  # クライアントの最終通信時刻を更新
        # 他の全クライアントにメッセージをリレー
        for client in clients.keys():
            if client != addr:  # 送信元以外に送信
                try:
                    self.transport.sendto(data, client)  # UDPでデータを送信
                except Exception as e:
                    print(f"Failed to send message to {client}: {e}")  # 送信失敗時のエラー表示

ChatServerProtocol クラスに connection_madedatagram_received などのメソッドを定義している理由は、
asyncio.DatagramProtocol の仕組みで、これらのメソッドが「自動的に呼び出されるコールバック」だからです。


詳しく

  • asyncio.create_datagram_endpoint()ChatServerProtocol のインスタンスを作ると、
    UDPソケットでイベント(接続確立・データ受信など)が発生したときに
    connection_madedatagram_received などが自動的に呼ばれます

  • つまり、自分で直接呼び出す必要はなく、asyncioのイベントループが適切なタイミングで呼び出してくれます


  • UDPパケットを受信したとき → datagram_received(self, data, addr) が呼ばれる
  • ソケットが作成されたとき → connection_made(self, transport) が呼ばれる

まとめ:
ChatServerProtocol のメソッドは「自分で呼ぶため」ではなく、「asyncioのイベントループが自動で呼ぶため」に定義されています。
これはPythonの非同期ネットワークプログラミングの一般的な設計です。


公式ドキュメント


参考になる解説記事