Pythonで学ぶUDPデータグラム通信:送信・受信プログラムの基本
クライアントとサーバーの間では、ユーザーデータグラムプロトコル(UDP)を使ってデータのかたまり(データグラム)がやり取りされます。通信を確立するには、両方の端点がIPアドレスとポート番号を知っている必要があります。一方の端点を「送信者」、もう一方を「受信者」と呼びます。
UDPの大きな特徴は、接続を事前に確立しないコネクションレス型の通信であるという点です。送信者は送ったパケットの到達を追跡せず、パケットを受け取るかどうかは受信者の判断に委ねられます。そのためTCPよりもオーバーヘッドが小さく高速ですが、信頼性は保証されません。リアルタイム配信やオンラインゲームなど、速度が重視される場面でよく使われます。
送信側プログラム
以下のPythonプログラムは、標準ライブラリのsocketモジュールを使って送信側の処理を実装したものです。まずIPアドレスとポート番号の変数を宣言し、送信するメッセージを定義します。そしてsendto()メソッドを使うことで、メッセージと宛先(IPアドレス・ポート番号)を組み合わせて一度に送信できます。
例
import socket
UDP_IP = "localhost"
UDP_PORT = 5050
MESSAGE = "Hello UDP! "
print("Sent Message: ", MESSAGE)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(bytes(MESSAGE, "utf-8"), (UDP_IP, UDP_PORT))出力
上記のコードを実行すると、次のような結果が得られます。
Sent Message: Hello UDP!
ここではsocket.socket()の第一引数にAF_INET(IPv4)、第二引数にSOCK_DGRAM(UDP用のソケットタイプ)を指定している点に注目してください。TCPの場合はSOCK_STREAMを指定しますが、UDPではSOCK_DGRAMを使用します。
受信側プログラム
同様に、送信側プログラムから送られてきたメッセージを受け取る受信側プログラムを作成します。以下の例では、1回に受け取れるメッセージのサイズを1024バイトに制限しています。bind()関数は、指定したIPアドレスとポート番号をソケットに紐付ける役割を担います。
例
import socket
UDP_IP = "localhost"
UDP_PORT = 5050
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((UDP_IP, UDP_PORT))
while True:
# バッファサイズは1024バイト
data, addr = s.recvfrom(1024)
print("Received message:", data)出力
上記のコードを実行すると、次のような結果が得られます。
Received message: Hello UDP!
recvfrom()は受信したデータとともに、送信元のアドレス情報(addr)も返します。これにより、誰からデータが届いたかを把握することも可能です。whileループで囲むことで、プログラムは継続的にメッセージを待ち受け続けます。
まとめ
Pythonのsocketモジュールを使えば、UDPによるデータグラム通信を非常にシンプルなコードで実装できます。送信側はsendto()、受信側はbind()とrecvfrom()という最小限のAPIだけで双方向の通信が成立します。信頼性よりも速さや軽量さが求められるアプリケーションを開発する際には、ぜひUDP通信を活用してみてください。
-
Pythonの低レベルネットワークインターフェース(ソケット)の基礎と使い方
Pythonの標準ライブラリに含まれる「socket」モジュールは、OSが提供するソケットエンドポイントを利用して、サーバーマシンとクライアントマシンが通信するための仕組みを定義しています。socket APIには、コネクション型(接続指向)プロトコルとコネクションレス型(非接続型)プロトコルの両方に対応した関数が用意されています。 ソケットとは、双方向通信リンクの「終端(エンドポイント)」のことです。IPアドレスとポート番号によって識別され、通信を開始するには両端でソケットを適切に設定する必要があります。これにより、クライアント・サーバー環境において、着信メッセージを待ち受け、応答を送り返
-
Pythonのソケットエラー48(Address already in use)の原因と解決策
ソケットエラー48は、プロセスがすでに使用中のポートへバインドしようとした際に発生するPythonのエラーです。エラーメッセージとしては「socket.error: [Errno 48] Address already in use」と表示されます。「socket.error: [Errno 48] Address already in use」エラーの原因調査の結果、このエラーの主な原因は以下の通りです。ポートへのプロセスのバインド: サーバー上でプロセスを作成すると、インターネットと通信するためにポートが使用されます。ポートとは、一度に一人のゲストしか受け入れられないホストのようなものです