Open1
class ChatServerProtocol(asyncio.DatagramProtocol):
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_made
や datagram_received
などのメソッドを定義している理由は、
asyncio.DatagramProtocol
の仕組みで、これらのメソッドが「自動的に呼び出されるコールバック」だからです。
詳しく
-
asyncio.create_datagram_endpoint()
でChatServerProtocol
のインスタンスを作ると、
UDPソケットでイベント(接続確立・データ受信など)が発生したときに
connection_made
やdatagram_received
などが自動的に呼ばれます。 -
つまり、自分で直接呼び出す必要はなく、asyncioのイベントループが適切なタイミングで呼び出してくれます。
例
- UDPパケットを受信したとき →
datagram_received(self, data, addr)
が呼ばれる - ソケットが作成されたとき →
connection_made(self, transport)
が呼ばれる
まとめ:
ChatServerProtocol
のメソッドは「自分で呼ぶため」ではなく、「asyncioのイベントループが自動で呼ぶため」に定義されています。
これはPythonの非同期ネットワークプログラミングの一般的な設計です。