ESP32 AsyncUDP Library – listen()

Home / References / ESP32 Library / AsyncUDP Library

This webpage is part of the Comprehensive Guide to the ESP32 Arduino Core Library, accessible on AvantMaker.com.

Description

The listen() method is used to bind the AsyncUDP object to a specific port and optionally to a specific IP address, enabling it to receive incoming UDP packets. When called, this method initializes the internal UDP control block, starts the UDP task, closes any existing connections, and binds the socket to the specified address and port. Unlike the connect() method which sets a default destination for outgoing packets, the listen() method configures the UDP socket to act as a server that can receive packets from any client. The method supports binding to a specific IP address for selective listening or to any available interface. This is essential for UDP server applications that need to receive data from multiple clients, handle broadcast packets, or implement request-response communication patterns where the server responds to incoming client requests.

Syntax and Usage

The listen() method has three overloaded versions:

Listen on any interface: 

bool success = udp.listen(port)

Binds to all available network interfaces on the specified port.

Listen on specific IP: 

bool success = udp.listen(localIP, port)

Binds to a specific IP address and port using IPAddress object.

Listen with ip_addr_t: 

bool success = udp.listen(addr, port)

Binds to a specific address using low-level ip_addr_t structure.

For practical applications and examples of this method, please consult the “Example Code” section on this page. This section provides comprehensive guidance to help you better understand and apply the method effectively.

Arguments

  • port (uint16_t) – The local port number to bind to and listen on. Valid range is 1-65535, though ports below 1024 typically require special privileges.
  • localIP (IPAddress) – The specific local IP address to bind to. Can be IPv4 or IPv6 address. If not specified, binds to all available interfaces.
  • addr (const ip_addr_t*) – Pointer to a low-level IP address structure for specific interface binding.

Return Value

The listen() method returns a bool value indicating the success of the bind operation. It returns true if the socket was successfully bound to the specified address and port, meaning the UDP task started properly, the internal UDP control block was initialized, and the binding operation completed without conflicts. It returns false if any error occurred during the process, such as failure to start the UDP task, inability to initialize the UDP control block, port already in use, or invalid binding parameters. You can use the lastErr() method to get more detailed error information if the listen operation fails. After successful binding, you should set up a packet handler using onPacket() to process incoming UDP packets.

This page is part of the Comprehensive Guide to the ESP32 Arduino Core Library, accessible on AvantMaker.com.

Example Code

UDP Server with Advanced Packet Processing and Client Management

This example demonstrates how to use the listen() method to create a comprehensive UDP server that can handle multiple clients, process different types of messages, and maintain statistics. The server listens on a specific port, processes incoming packets with detailed analysis, maintains client information, and provides various response mechanisms including echo, broadcast, and custom commands.

How to use this example: Upload this code to your ESP32 and replace the WiFi credentials. The server will automatically start listening on port 1234 and handle incoming UDP packets. You can test it by sending UDP packets from various clients, including broadcast messages. The server responds to different command types: “echo” for message echoing, “info” for server information, “stats” for statistics, and “broadcast” to trigger server-initiated broadcasts. Monitor the Serial output to see detailed packet processing logs and server statistics.

Testing with the connect() example: This server example works perfectly with the UDP client example from the connect() method webpage. Upload this server code to one ESP32 and the client code to another ESP32 on the same network. Update the client’s server IP address to match this server’s IP address. The client will automatically send various commands (info, stats, echo, clients) that this server is designed to process and respond to. You’ll see real-time communication between both devices with detailed logs showing the complete UDP request-response cycle.

Setup Instructions for Two-Device Testing:

  1. Server Setup: Upload this listen() example code to your first ESP32. After WiFi connection, note the IP address displayed in the Serial Monitor.
  2. Client Setup: Upload the connect() example code to your second ESP32. Update the client’s serverIP variable with the IP address from step 1.
  3. Expected Behavior: The client will connect and send rotating commands: info, stats, echo messages, and client list requests. The server will respond to each command appropriately, and both devices will display detailed communication logs.
/*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use the listen() method to create a
 * comprehensive UDP server that can handle multiple clients, process different
 * types of messages, and maintain statistics. The server listens on a specific
 * port, processes incoming packets with detailed analysis, maintains client
 * information, and provides various response mechanisms.
 *
 * How to use this example:
 * Upload this code to your ESP32 and replace the WiFi credentials. The server
 * will automatically start listening on port 1234 and handle incoming UDP
 * packets. You can test it by sending UDP packets from various clients.
 * The server responds to different command types: "echo" for message echoing,
 * "info" for server information, "stats" for statistics, and "broadcast"
 * to trigger server-initiated broadcasts. Monitor the Serial output to see
 * detailed packet processing logs and server statistics.
 *
 * Code Source:
 * This example code is sourced from the Comprehensive Guide
 * to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
 * For additional code examples and in-depth documentation related to
 * the ESP32 Arduino Core Library, please visit:
 *
 * https://avantmaker.com/home/all-about-esp32-arduino-core-library/
 *
 * AvantMaker.com, your premier destination for all things
 * DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
 * to empowering makers, learners, and enthusiasts with
 * the resources they need to bring their innovative ideas to life.
 */

#include <WiFi.h>
#include <AsyncUDP.h>

// WiFi credentials
const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";

// Server configuration
const uint16_t serverPort = 1234;
IPAddress serverIP;  // Will be set after WiFi connection

AsyncUDP udp;

// Client tracking structure
struct ClientInfo {
  IPAddress ip;
  uint16_t port;
  unsigned long lastSeen;
  unsigned long packetsReceived;
  unsigned long bytesReceived;
  String lastMessage;
};

// Server statistics and client management
struct ServerStats {
  unsigned long totalPacketsReceived = 0;
  unsigned long totalBytesSent = 0;
  unsigned long totalBytesReceived = 0;
  unsigned long totalClientsSeen = 0;
  unsigned long serverStartTime = 0;
  unsigned long broadcastsSent = 0;
  std::vector<ClientInfo> clients;
} stats;

// Timing control
unsigned long lastStatsReport = 0;
unsigned long lastBroadcast = 0;
const unsigned long statsInterval = 60000;     // Report stats every 60 seconds
const unsigned long broadcastInterval = 120000; // Send broadcast every 2 minutes
const unsigned long clientTimeout = 300000;    // Client timeout after 5 minutes

void setup() {
  Serial.begin(115200);
  Serial.println("Starting ESP32 AsyncUDP Server with listen() method...");
  
  // Initialize WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected successfully!");
  
  serverIP = WiFi.localIP();
  Serial.print("Server IP address: ");
  Serial.println(serverIP);
  Serial.print("Signal strength: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
  
  // Start UDP server using listen() method
  startUDPServer();
}

void startUDPServer() {
  Serial.println("=== Starting UDP Server ===");
  Serial.print("Attempting to listen on port: ");
  Serial.println(serverPort);
  
  // Use listen() method to bind to the specified port
  if (udp.listen(serverPort)) {
    Serial.println("✅ UDP Server started successfully!");
    Serial.print("Listening on: ");
    Serial.print(serverIP);
    Serial.print(":");
    Serial.println(serverPort);
    
    stats.serverStartTime = millis();
    
    // Set up packet handler for incoming packets
    udp.onPacket([](AsyncUDPPacket packet) {
      handleIncomingPacket(packet);
    });
    
    Serial.println("📡 Server ready to receive UDP packets...");
    Serial.println("📋 Supported commands: echo, info, stats, broadcast");
    
  } else {
    Serial.println("❌ Failed to start UDP server!");
    Serial.print("Last error code: ");
    Serial.println(udp.lastErr());
    
    // Retry after delay
    Serial.println("Will retry server start in 10 seconds...");
    delay(10000);
    startUDPServer();
  }
}

void handleIncomingPacket(AsyncUDPPacket packet) {
  stats.totalPacketsReceived++;
  stats.totalBytesReceived += packet.length();
  
  // Extract packet information
  IPAddress clientIP = packet.remoteIP();
  uint16_t clientPort = packet.remotePort();
  String message = "";
  
  // Convert packet data to string
  for (size_t i = 0; i < packet.length(); i++) {
    message += (char)packet.data()[i];
  }
  message.trim();
  
  Serial.println("📥 === Incoming UDP Packet ===");
  Serial.print("From: ");
  Serial.print(clientIP);
  Serial.print(":");
  Serial.println(clientPort);
  Serial.print("To: ");
  Serial.print(packet.localIP());
  Serial.print(":");
  Serial.println(packet.localPort());
  Serial.print("Length: ");
  Serial.print(packet.length());
  Serial.println(" bytes");
  Serial.print("Type: ");
  Serial.println(packet.isBroadcast() ? "Broadcast" : 
                packet.isMulticast() ? "Multicast" : "Unicast");
  Serial.print("Message: '");
  Serial.print(message);
  Serial.println("'");
  
  // Update or add client information
  updateClientInfo(clientIP, clientPort, message);
  
  // Process the message and generate response
  processMessage(packet, message);
  
  Serial.println("=== End Packet Processing ===");
}

void updateClientInfo(IPAddress clientIP, uint16_t clientPort, const String& message) {
  bool clientFound = false;
  
  // Search for existing client
  for (auto& client : stats.clients) {
    if (client.ip == clientIP && client.port == clientPort) {
      client.lastSeen = millis();
      client.packetsReceived++;
      client.bytesReceived += message.length();
      client.lastMessage = message;
      clientFound = true;
      break;
    }
  }
  
  // Add new client if not found
  if (!clientFound) {
    ClientInfo newClient;
    newClient.ip = clientIP;
    newClient.port = clientPort;
    newClient.lastSeen = millis();
    newClient.packetsReceived = 1;
    newClient.bytesReceived = message.length();
    newClient.lastMessage = message;
    
    stats.clients.push_back(newClient);
    stats.totalClientsSeen++;
    
    Serial.print("🆕 New client registered: ");
    Serial.print(clientIP);
    Serial.print(":");
    Serial.println(clientPort);
  }
}

void processMessage(AsyncUDPPacket& packet, const String& message) {
  String response = "";
  String command = message;
  command.toLowerCase();
  
  if (command.startsWith("echo ")) {
    // Echo command - return the message after "echo "
    String echoMessage = message.substring(5);
    response = "ECHO: " + echoMessage;
    
  } else if (command == "info") {
    // Server information command
    response = "ESP32 UDP Server v1.0\\n";
    response += "IP: " + serverIP.toString() + "\\n";
    response += "Port: " + String(serverPort) + "\\n";
    response += "Uptime: " + String((millis() - stats.serverStartTime) / 1000) + "s\\n";
    response += "Free Heap: " + String(ESP.getFreeHeap()) + " bytes\\n";
    response += "WiFi Signal: " + String(WiFi.RSSI()) + " dBm";
    
  } else if (command == "stats") {
    // Statistics command
    response = "=== SERVER STATISTICS ===\\n";
    response += "Total Packets: " + String(stats.totalPacketsReceived) + "\\n";
    response += "Total Bytes RX: " + String(stats.totalBytesReceived) + "\\n";
    response += "Total Bytes TX: " + String(stats.totalBytesSent) + "\\n";
    response += "Active Clients: " + String(getActiveClientCount()) + "\\n";
    response += "Total Clients Seen: " + String(stats.totalClientsSeen) + "\\n";
    response += "Broadcasts Sent: " + String(stats.broadcastsSent);
    
  } else if (command == "broadcast") {
    // Trigger server broadcast
    sendBroadcastMessage("Server broadcast triggered by client request");
    response = "Broadcast message sent to all clients";
    
  } else if (command == "clients") {
    // List active clients
    response = "=== ACTIVE CLIENTS ===\\n";
    int activeCount = 0;
    for (const auto& client : stats.clients) {
      if (millis() - client.lastSeen < clientTimeout) {
        response += client.ip.toString() + ":" + String(client.port);
        response += " (Packets: " + String(client.packetsReceived) + ")\\n";
        activeCount++;
      }
    }
    if (activeCount == 0) {
      response += "No active clients";
    }
    
  } else {
    // Default response for unknown commands
    response = "Unknown command. Available: echo, info, stats, broadcast, clients";
  }
  
  // Send response back to client
  size_t sentBytes = packet.printf("%s", response.c_str());
  if (sentBytes > 0) {
    stats.totalBytesSent += sentBytes;
    Serial.print("📤 Response sent (");
    Serial.print(sentBytes);
    Serial.print(" bytes): ");
    Serial.println(response.substring(0, 50) + (response.length() > 50 ? "..." : ""));
  } else {
    Serial.println("❌ Failed to send response");
  }
}

void sendBroadcastMessage(const String& message) {
  size_t sentBytes = udp.broadcastTo(message.c_str(), serverPort);
  if (sentBytes > 0) {
    stats.broadcastsSent++;
    stats.totalBytesSent += sentBytes;
    Serial.print("📢 Broadcast sent (");
    Serial.print(sentBytes);
    Serial.print(" bytes): ");
    Serial.println(message);
  } else {
    Serial.println("❌ Failed to send broadcast");
  }
}

int getActiveClientCount() {
  int activeCount = 0;
  for (const auto& client : stats.clients) {
    if (millis() - client.lastSeen < clientTimeout) {
      activeCount++;
    }
  }
  return activeCount;
}

void cleanupInactiveClients() {
  auto it = stats.clients.begin();
  while (it != stats.clients.end()) {
    if (millis() - it->lastSeen > clientTimeout) {
      Serial.print("🧹 Removing inactive client: ");
      Serial.print(it->ip);
      Serial.print(":");
      Serial.println(it->port);
      it = stats.clients.erase(it);
    } else {
      ++it;
    }
  }
}

void reportStatistics() {
  Serial.println("📊 === SERVER STATISTICS REPORT ===");
  Serial.print("Server Uptime: ");
  Serial.print((millis() - stats.serverStartTime) / 1000);
  Serial.println(" seconds");
  Serial.print("Listening on: ");
  Serial.print(serverIP);
  Serial.print(":");
  Serial.println(serverPort);
  
  Serial.print("Total Packets Received: ");
  Serial.println(stats.totalPacketsReceived);
  Serial.print("Total Bytes Received: ");
  Serial.println(stats.totalBytesReceived);
  Serial.print("Total Bytes Sent: ");
  Serial.println(stats.totalBytesSent);
  Serial.print("Broadcasts Sent: ");
  Serial.println(stats.broadcastsSent);
  
  int activeClients = getActiveClientCount();
  Serial.print("Active Clients: ");
  Serial.print(activeClients);
  Serial.print(" / ");
  Serial.print(stats.totalClientsSeen);
  Serial.println(" total seen");
  
  // Calculate rates
  unsigned long uptimeSeconds = (millis() - stats.serverStartTime) / 1000;
  if (uptimeSeconds > 0) {
    float packetsPerSecond = (float)stats.totalPacketsReceived / uptimeSeconds;
    float bytesPerSecond = (float)stats.totalBytesReceived / uptimeSeconds;
    Serial.print("Average Packets/sec: ");
    Serial.println(packetsPerSecond, 2);
    Serial.print("Average Bytes/sec: ");
    Serial.println(bytesPerSecond, 2);
  }
  
  // System information
  Serial.print("Free Heap: ");
  Serial.print(ESP.getFreeHeap());
  Serial.println(" bytes");
  Serial.print("WiFi Signal: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
  Serial.println("===================================");
}

void loop() {
  unsigned long currentTime = millis();
  
  // Report statistics periodically
  if (currentTime - lastStatsReport >= statsInterval) {
    lastStatsReport = currentTime;
    reportStatistics();
    cleanupInactiveClients();
  }
  
  // Send periodic broadcast messages
  if (currentTime - lastBroadcast >= broadcastInterval) {
    lastBroadcast = currentTime;
    String broadcastMsg = "Server heartbeat - " + String(stats.totalPacketsReceived) + " packets processed";
    sendBroadcastMessage(broadcastMsg);
  }
  
  // Monitor WiFi connection
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("⚠️  WiFi connection lost! Attempting reconnection...");
    WiFi.reconnect();
    delay(5000);
  }
  
  // Small delay to prevent overwhelming the system
  delay(100);
}

For more ESP32 development resources and tutorials, visit the All About ESP32 Resources Hub on  AvantMaker.com

ESP32 Library Index

ESP32 Arduino Core Library


FAQ

Ready to experiment and explore more about ESP32? Visit our website’s All About ESP32 Resources Hub, packed with tutorials, guides, and tools to inspire your maker journey. Experiment, explore, and elevate your skills with everything you need to master this powerful microcontroller platform!

error: Content is protected !!