ESP32 AsyncUDP Library – close()

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 close() method is used to terminate and clean up an existing UDP connection or binding. When called, this method disconnects any active UDP connection established by the connect() method and resets the internal connection state to disconnected. The method performs essential cleanup operations including disconnecting the UDP protocol control block (PCB) if a connection exists, setting the internal connection flag to false, and preparing the AsyncUDP object for reuse. This method is automatically called internally by other methods like connect() and listen() before establishing new connections to ensure clean state transitions. It’s particularly useful for applications that need to dynamically change UDP endpoints, implement connection timeouts, or perform graceful shutdowns. The method ensures proper resource management and prevents memory leaks by cleaning up internal UDP structures when they are no longer needed.

Syntax and Usage

The close() method has a simple syntax:

Close UDP connection: 

udp.close()

Terminates any active UDP connection and resets the connection state.

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

The close() method takes no arguments.

Return Value

The close() method returns void (no return value). The method always executes its cleanup operations regardless of the current connection state. If the AsyncUDP object is already disconnected or was never connected, calling close() is safe and will have no adverse effects. After calling this method, the connected() method will return false, indicating that the UDP object is no longer in a connected state and is ready for new connection operations.

Example Code

UDP Connection Manager with Dynamic Endpoint Switching

This example demonstrates how to use the close() method to implement a UDP connection manager that can dynamically switch between different server endpoints. The application connects to multiple servers in sequence, sends data to each one, properly closes connections using the close() method, and maintains detailed statistics about connection lifecycles and data transmission.

How to use this example: Upload this code to your ESP32 and replace the WiFi credentials. Configure the server list with your available UDP servers. The application will automatically cycle through different servers, connecting to each one, sending test data, properly closing the connection, and moving to the next server. Monitor the Serial output to see detailed connection management logs, data transmission statistics, and the proper usage of the close() method for clean connection transitions.

/*
 * Author: Avant Maker
 * Date: June 18, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use the close() method to implement a UDP
 * connection manager that can dynamically switch between different server
 * endpoints. The application connects to multiple servers in sequence, sends
 * data to each one, properly closes connections using the close() method,
 * and maintains detailed statistics about connection lifecycles.
 *
 * How to use this example:
 * Upload this code to your ESP32 and replace the WiFi credentials. Configure
 * the server list with your available UDP servers. The application will
 * automatically cycle through different servers, connecting to each one,
 * sending test data, properly closing the connection, and moving to the next
 * server. Monitor the Serial output to see detailed connection management
 * logs and proper usage of the close() method.
 *
 * 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";

// UDP server configuration - configure multiple servers for testing
struct ServerConfig {
  IPAddress ip;
  uint16_t port;
  String name;
  String description;
};

ServerConfig servers[] = {
  {IPAddress(192, 168, 1, 100), 1234, "Primary Server", "Main data collection server"},
  {IPAddress(192, 168, 1, 101), 1234, "Backup Server", "Secondary backup server"},
  {IPAddress(192, 168, 1, 102), 5678, "Analytics Server", "Data analytics and processing"},
  {IPAddress(192, 168, 1, 103), 9999, "Logging Server", "System logging and monitoring"}
};
const int numServers = sizeof(servers) / sizeof(servers[0]);

AsyncUDP udp;

// Connection management and statistics
struct ConnectionManager {
  int currentServerIndex = 0;
  unsigned long totalConnections = 0;
  unsigned long totalDisconnections = 0;
  unsigned long totalPacketsSent = 0;
  unsigned long totalPacketsReceived = 0;
  unsigned long totalBytesSent = 0;
  unsigned long totalBytesReceived = 0;
  unsigned long connectionStartTime = 0;
  unsigned long totalConnectionTime = 0;
  bool isConnected = false;
  String lastError = "";
} manager;

// Timing control
const unsigned long connectionDuration = 15000;    // Stay connected for 15 seconds
const unsigned long sendInterval = 3000;           // Send data every 3 seconds
const unsigned long switchDelay = 2000;            // Wait 2 seconds between server switches
unsigned long lastSendTime = 0;
unsigned long connectionTimer = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting ESP32 AsyncUDP Connection Manager with close() 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!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Signal strength: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
  
  // Start connection management cycle
  Serial.println("Starting UDP connection management cycle...");
  connectToNextServer();
}

void connectToNextServer() {
  // Ensure any existing connection is properly closed
  if (manager.isConnected) {
    closeCurrentConnection();
  }
  
  // Get current server configuration
  ServerConfig& server = servers[manager.currentServerIndex];
  
  Serial.println("=== Connecting to Next Server ===");
  Serial.print("Server Index: ");
  Serial.print(manager.currentServerIndex + 1);
  Serial.print("/");
  Serial.println(numServers);
  Serial.print("Server Name: ");
  Serial.println(server.name);
  Serial.print("Description: ");
  Serial.println(server.description);
  Serial.print("Address: ");
  Serial.print(server.ip);
  Serial.print(":");
  Serial.println(server.port);
  
  // Attempt connection
  if (udp.connect(server.ip, server.port)) {
    Serial.println("✅ Connection established successfully!");
    manager.isConnected = true;
    manager.totalConnections++;
    manager.connectionStartTime = millis();
    connectionTimer = millis();
    
    // Set up packet handler
    udp.onPacket([](AsyncUDPPacket packet) {
      handleIncomingPacket(packet);
    });
    
    // Send initial connection message
    String welcomeMsg = "Connected to " + server.name + " from " + WiFi.localIP().toString();
    sendMessage(welcomeMsg);
    
  } else {
    Serial.println("❌ Connection failed!");
    Serial.print("Error code: ");
    Serial.println(udp.lastErr());
    manager.lastError = "Connection failed to " + server.name;
    
    // Move to next server after delay
    delay(switchDelay);
    moveToNextServer();
  }
}

void closeCurrentConnection() {
  if (!manager.isConnected) {
    return; // Nothing to close
  }
  
  Serial.println("🔒 === Closing Current Connection ===");
  Serial.print("Closing connection to: ");
  Serial.println(servers[manager.currentServerIndex].name);
  
  // Calculate connection duration
  unsigned long connectionDuration = millis() - manager.connectionStartTime;
  manager.totalConnectionTime += connectionDuration;
  
  Serial.print("Connection duration: ");
  Serial.print(connectionDuration / 1000.0, 2);
  Serial.println(" seconds");
  
  // Use close() method to properly terminate the connection
  udp.close();
  
  // Verify connection is closed
  if (!udp.connected()) {
    Serial.println("✅ Connection closed successfully");
    manager.isConnected = false;
    manager.totalDisconnections++;
  } else {
    Serial.println("⚠️  Warning: Connection may not be fully closed");
  }
  
  Serial.println("=== Connection Closed ===");
}

void handleIncomingPacket(AsyncUDPPacket packet) {
  manager.totalPacketsReceived++;
  manager.totalBytesReceived += packet.length();
  
  Serial.println("📥 Received response:");
  Serial.print("  From: ");
  Serial.print(packet.remoteIP());
  Serial.print(":");
  Serial.println(packet.remotePort());
  Serial.print("  Data: ");
  Serial.write(packet.data(), packet.length());
  Serial.println();
}

void sendMessage(const String& message) {
  if (!manager.isConnected || !udp.connected()) {
    Serial.println("⚠️  Cannot send - not connected");
    return;
  }
  
  size_t sentBytes = udp.print(message);
  if (sentBytes > 0) {
    manager.totalPacketsSent++;
    manager.totalBytesSent += sentBytes;
    Serial.println("📤 Message sent:");
    Serial.print("  To: ");
    Serial.println(servers[manager.currentServerIndex].name);
    Serial.print("  Message: ");
    Serial.println(message);
    Serial.print("  Size: ");
    Serial.print(sentBytes);
    Serial.println(" bytes");
  } else {
    Serial.println("❌ Failed to send message");
  }
}

void moveToNextServer() {
  manager.currentServerIndex = (manager.currentServerIndex + 1) % numServers;
  
  if (manager.currentServerIndex == 0) {
    Serial.println("🔄 Completed full server cycle, starting over...");
    printDetailedStatistics();
  }
  
  delay(switchDelay);
  connectToNextServer();
}

void sendPeriodicData() {
  if (!manager.isConnected) {
    return;
  }
  
  ServerConfig& server = servers[manager.currentServerIndex];
  String dataMessage = "Data from " + WiFi.localIP().toString() + 
                      " to " + server.name + 
                      " - Packet #" + String(manager.totalPacketsSent + 1) +
                      " - Uptime: " + String(millis() / 1000) + "s";
  
  sendMessage(dataMessage);
}

void printDetailedStatistics() {
  Serial.println("📊 === DETAILED CONNECTION STATISTICS ===");
  Serial.print("Total Connections: ");
  Serial.println(manager.totalConnections);
  Serial.print("Total Disconnections: ");
  Serial.println(manager.totalDisconnections);
  Serial.print("Total Packets Sent: ");
  Serial.println(manager.totalPacketsSent);
  Serial.print("Total Packets Received: ");
  Serial.println(manager.totalPacketsReceived);
  Serial.print("Total Bytes Sent: ");
  Serial.println(manager.totalBytesSent);
  Serial.print("Total Bytes Received: ");
  Serial.println(manager.totalBytesReceived);
  Serial.print("Total Connection Time: ");
  Serial.print(manager.totalConnectionTime / 1000.0, 2);
  Serial.println(" seconds");
  
  if (manager.totalConnections > 0) {
    float avgConnectionTime = (float)manager.totalConnectionTime / manager.totalConnections;
    Serial.print("Average Connection Duration: ");
    Serial.print(avgConnectionTime / 1000.0, 2);
    Serial.println(" seconds");
  }
  
  Serial.print("Current Server: ");
  Serial.print(manager.currentServerIndex + 1);
  Serial.print("/");
  Serial.println(numServers);
  Serial.print("Connection Status: ");
  Serial.println(manager.isConnected ? "Connected ✅" : "Disconnected ❌");
  
  if (!manager.lastError.isEmpty()) {
    Serial.print("Last Error: ");
    Serial.println(manager.lastError);
  }
  
  // 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();
  
  // Check if it's time to switch servers
  if (manager.isConnected && (currentTime - connectionTimer >= connectionDuration)) {
    Serial.println("⏰ Connection duration reached, switching servers...");
    closeCurrentConnection();
    moveToNextServer();
    return;
  }
  
  // Send periodic data
  if (manager.isConnected && (currentTime - lastSendTime >= sendInterval)) {
    lastSendTime = currentTime;
    sendPeriodicData();
  }
  
  // Monitor WiFi connection
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("⚠️  WiFi connection lost! Attempting reconnection...");
    if (manager.isConnected) {
      closeCurrentConnection();
    }
    WiFi.reconnect();
    delay(5000);
  }
  
  // Print periodic statistics
  static unsigned long lastStatsTime = 0;
  if (currentTime - lastStatsTime >= 60000) { // Every 60 seconds
    lastStatsTime = currentTime;
    printDetailedStatistics();
  }
  
  delay(100);
}

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 !!