WiFiUDP の解説と実装リファレンス
【概要】
WiFiUDP クラスは、Arduino環境(主にESP8266およびESP32)において、Wi-Fiネットワーク経由でUDP(User Datagram Protocol)プロトコルを用いた通信を行うためのライブラリです。
UDPはTCPと比較してコネクションの確立(3ウェイ・ハンドシェイク)を行わないため、低遅延かつオーバーヘッドの少ない通信が可能です。このクラスは、UDPソケットの作成、パケットの受信、送信、およびリモートホスト情報の取得を抽象化し、標準的なArduinoのプログラミングモデルで操作できるように提供されます。
【仕様】
主要なメソッドと関数
| 関数名 | 引数 | 戻り値 | 説明 |
| WiFiUDP(uint16_t port) | port (uint16_t) | なし | 指定したポート番号でUDPソケットを初期化するコンストラクタ。 |
| begin() | なし | なし | UDPソケットをアクティブな状態にする。 |
| parsePacket() | なし | bool | 受信バッファにパケットが存在するか確認し、存在する場合は内部ポインタを更新する。 |
| packetAvailable() | なし | bool | 受信可能なパケットがあるかを確認する(parsePacketと類似)。 |
| dump() | なし | なし | 受信したパケットの全内容をシリアル出力に表示する。 |
| write() | uint8_t* (payload), size_t (length) | size_t | パケットを送信し、実際に送信されたバイト数を返す。 |
| remote_IP() | なし | IPAddress | 送信元(パケット送信元)のIPアドレスを取得する。 |
| remote_port() | なし | uint16_t | 送信元ポート番号を取得する。 |
| packetSize() | なし | size_t | 受信パケットのサイズを取得する。 |
データ型と初期状態
- ポート番号: 0〜65535(16ビット符号なし整数)。
- バッファ処理: 内部的に受信バッファを保持するが、巨大なパケットの処理には注意が必要。
- 初期状態: オブジェクト生成直後は初期化されておらず、
begin()の呼び出しが必要。
【技術的特徴】
UDP vs TCP (WiFiClient)
- 信頼性:
WiFiUDPは「ベストエフォート」型の配送を行うため、パケットの到着保証や順序保証、再送制御は行われません。これに対しWiFiClient(TCP)は信頼性を保証します。 - オーバーヘッド: UDPはヘッダサイズが小さく、通信の確立を必要としないため、リアルタイム性が求められる用途に適しています。
- 非ブロッキング挙動: 一般的に、UDPの送信は送信バッファに書き込めば完了とみなされるため、TCPのような「送信完了待ち」のブロッキングが発生しにくい性質があります。
ハードウェアレベルの挙動
- ソケット管理: ESP32/ESP8266のWi-Fiスタック(LwIPなど)と連携し、ハードウェアのネットワークインターフェースを介してパケットを処理します。
- マルチキャスト/ブロードキャスト:
WiFiUDPを通じて、ネットワーク内の特定グループ(マルチキャスト)や全ホスト(ブロードキャスト)へのパケット送信をサポートします。
【注意点】
- パケット損失: 通信環境が不安定な場合、パケットは消失する可能性があります。重要なデータの送信にはアプリケーション層でのシーケンス番号やACKの設計が必要です。
- MTU制限: 通常のEthernet/Wi-Fi環境ではMTU(Maximum Transmission Unit)は1500バイト程度です。これを超えるサイズのパケットを一度に送信しようとすると、断片化(フラグメンテーション)が発生するか、破棄される可能性があります。
- リソース制約: 受信バッファはメモリを消費します。極端に大きなパケットの受信は、スタックオーバーフローやメモリ不足の原因となる可能性があります。
- 割り込みの影響:
parsePacket()を実行するタイミングによっては、受信バッファが上書きされる可能性があります。高頻度でデータを受信する際は、受信間隔と処理速度のバランスを考慮する必要があります。 - 非同期処理: 受信パケットの処理が重い場合、次のパケットの処理を遅延させる可能性があります。重い処理は別タスク(ESP32のFreeRTOS等)にオフロードすることを推奨します。
【サンプルコード】
以下は、特定ポートで待機し、受信したデータを受信元とともに表示するUDPサーバーの基本実装です。
#include <WiFi.h>
#include <WiFiUDP.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
WiFiUDP udp;
unsigned int localPort = 4210; // 受信ポート
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to WiFi");
udp.begin(localPort);
Serial.print("Listening on port: ");
Serial.println(localPort);
}
void loop() {
int packetSize = udp.parsePacket();
if (packetSize) {
Serial.print("Received packet from: ");
Serial.print(udp.remoteIP());
Serial.print(" : ");
Serial.print(udp.remotePort());
while (udp.available()) {
char c = udp.read();
Serial.print(c);
}
Serial.println();
}
}
【活用例】
- IoTセンサー監視: 多数のデバイスから定期的にセンサー値を送信する「ハートビート」信号の受信。
- 低遅延ビデオ/音声ストリーミング: 信頼性よりもリアルタイム性が重視されるメディアデータの転送。
- DNSクエリ/簡易コマンド制御: 簡潔なコマンド(例:
"LIGHT_ON")を特定のポートに投げて機器を操作するインターフェース。 - マルチキャスト・ディスカバリー: ネットワーク内の特定のデバイスを探索するためのプロトコル実装。


コメント