ESP32-UDP通信 (Arduino)

ESP32配置UDP通信

介绍


用户数据报协议UDP

UDP(User Datagram Protocol)是一种在计算机网络中常用的传输层协议,它与TCP(Transmission Control Protocol)一样属于传输层协议的一种。UDP主要用于在网络中传输数据,但与TCP不同,它是一种面向无连接的协议,不提供可靠性、流控制和错误恢复等特性。

以下是TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)的一些主要对比特点:

特点 TCP UDP
连接方式 面向连接 面向无连接
可靠性 提供可靠的数据传输,保证数据的完整性、顺序性 不提供数据可靠性保障,无顺序保证
流控制 提供流量控制机制,避免网络拥塞 不提供流量控制,数据发送不受限制
差错检测与恢复 提供差错检测和自动重传机制,确保数据的正确传输 不提供差错检测和重传,数据可能丢失或损坏
适用场景 文件传输、网页浏览等对可靠性要求较高的应用 实时性要求较高的应用,如音频、视频传输
顺序保证 保证数据包的顺序传输 不保证数据包的顺序传输
连接建立和断开 三次握手建立连接,四次挥手断开连接 无连接建立和断开过程
面向字节 是的,以字节为单位进行数据传输 是的,以字节为单位进行数据传输
开销 较高,需要维护连接状态、流控制等 较低,无连接状态维护,适用于实时性要求高的应用
适用性 适用于对可靠性要求较高的应用 适用于对实时性要求较高的应用

总而言之,TCP适用于需要可靠性和顺序性的应用,而UDP适用于对实时性要求较高、能够容忍一定数据丢失的应用。

四层网络模型

请添加图片描述
TCP/IP 四层网络协议体系结构,用于指导互联网上数据的传输和通信。该模型的四个层次分别是:

  1. 链路层 (Link Layer):

    • 功能:负责定义与物理网络介质的接口,处理通过该介质的原始比特流。该层通常包括设备驱动程序和网络接口卡 (NIC)。
    • 协议:通常使用的协议包括以太网 (Ethernet)、Wi-Fi、PPP (Point-to-Point Protocol) 等。
  2. 网络层 (Internet Layer):

    • 功能:负责在不同网络之间路由数据包,实现源到目标主机的数据传输。这一层的主要目标是确保数据从源主机传输到目标主机,即实现端到端的通信。
    • 协议:主要协议是 Internet Protocol (IP),包括 IPv4 和 IPv6。
  3. 传输层 (Transport Layer):

    • 功能:提供端到端的通信,负责数据的分段、重组和流量控制。该层主要确保数据在源和目标主机之间的可靠传输。
    • 协议:主要协议包括 Transmission Control Protocol (TCP) 和 User Datagram Protocol (UDP)。
  4. 应用层 (Application Layer):

    • 功能:提供网络服务和应用程序之间的接口,允许用户访问网络上的各种服务。这一层包含了各种应用层协议,支持不同的网络应用。
    • 协议:包括常见的应用层协议如 Hypertext Transfer Protocol (HTTP)、File Transfer Protocol (FTP)、Simple Mail Transfer Protocol (SMTP) 等。

基本方法


ESP32的基本UDP设置流程:

  1. 引入库文件: 引入必要的网络功能库文件<WiFi.h>

    #include <Arduino.h>
    #include <WiFi.h>
    
  2. 声明UDP对象: 使用WiFiUDP类声明一个UDP对象,该对象将用于处理UDP通信。

    WiFiUDP udp;
    
  3. 设置WiFi连接:setup函数中,配置ESP32的WiFi连接。将ESP32设置为SoftAP(访问点)模式,并指定SSID和密码。

    WiFi.softAP("ESP32_UDP", "987654321");
    
  4. 初始化UDP:setup函数中,使用udp.begin(port)初始化UDP。这里的port参数指定UDP服务器监听的端口号。

    udp.begin(1133);
    
  5. 串口打印IP地址(可选):setup函数中,可以使用Serial.println(WiFi.softAPIP())将分配给SoftAP的IP地址打印到串口监视器,以便调试和验证连接。

    Serial.println(WiFi.softAPIP());
    
  6. 处理UDP数据:loop函数中,使用udp.parsePacket()检查是否有传入的UDP数据包。如果有,可以使用udp.read()读取数据,并进行相应的处理。这里我将读取到的数据回发给客户端。

    if (udp.parsePacket()) {
      char val = udp.read();
      // 处理接收到的数据
      // 回发数据给客户端
      udp.beginPacket(udp.remoteIP(), udp.remotePort());
      udp.println(val);
      udp.endPacket();
    }
    
    1. udp.beginPacket(udp.remoteIP(), udp.remotePort());

      • beginPacket()函数用于开始构建UDP数据包,指定了目标设备的IP地址和端口号。
      • udp.remoteIP()用于获取远程设备的IP地址。
      • udp.remotePort()用于获取远程设备的端口号。
    2. udp.println(val);

      • println()函数用于将数据写入UDP数据包。在这里,它将变量 val 的值写入数据包。
      • udp对象是已经声明的WiFiUDP对象,它管理UDP通信。
    3. udp.endPacket();

      • endPacket()函数用于结束UDP数据包的构建,并将数据包发送到之前指定的远程设备的IP地址和端口号。

    这三行代码一起完成了以下操作:

    • 开始构建一个UDP数据包,指定目标设备的IP地址和端口号。
    • 将数据写入UDP数据包,这里是将变量 val 的值写入。
    • 结束UDP数据包的构建,并将数据包发送到远程设备。

这样,ESP32通过UDP协议回发了接收到的数据给远程设备。要注意的是在UDP通信设备之间可以交换数据包 而无需先建立连接。

当读取多个字节时

修改代码:

void loop() {
  if (udp.parsePacket()) {
    char* val = new char[256];  // 使用 new 动态分配一个数组,假设你想读取最多 255 个字节,为 null 终止符留下空间
    int bytesRead = udp.read(val, 255);  // 读取最多 255 个字节

    val[bytesRead] = '';  // 加上 null 终止符

    // 处理并打印接收到的数据
    Serial.println(val);

    // 将接收到的数据发送回客户端
    udp.beginPacket(udp.remoteIP(), udp.remotePort());
    udp.write(val, bytesRead);
    udp.endPacket();

    delete[] val;  // 使用 delete[] 释放动态分配的数组内存
  }
}

修改后的代码中:

  • 使用 new char[256]; 动态分配了一个数组来存储接收到的数据。
  • udp.read(val, 255); 读取最多 255 个字节,确保有空间容纳 null 终止符。
  • 添加 val[bytesRead] = ''; 来添加 null 终止符,使其适用于使用 Serial.println 打印。
  • 使用 delete[] val; 来释放使用 new 分配的数组内存。

请注意,在使用 new 动态分配内存后,必须使用 deletedelete[] 进行释放,以防止内存泄漏。

常用API


以下是Arduino ESP32中涉及UDP通信的一些关键API的总结:

  1. WiFiUDP类:

    • WiFiUDP类用于处理UDP通信。
    • 成员函数:
      • begin(port): 初始化UDP并指定监听的端口号。
      • beginPacket(ip, port): 打包一个UDP数据包准备将数据发送到指定的IP地址和端口。
      • endPacket(): 结束UDP数据包,发送数据到指定的IP地址和端口。
      • write(data, size): 将指定大小的数据写入UDP数据包。
      • parsePacket(): 检查是否有新的UDP数据包到达。
      • read(): 读取一个字节的数据。
      • remoteIP(): 获取远程设备的IP地址。
      • remotePort(): 获取远程设备的端口号。
  2. WiFi类:

    • WiFi类用于处理ESP32的WiFi连接。
    • 成员函数:
      • softAP(ssid, password): 将ESP32设置为SoftAP模式,并指定SSID和密码。
      • softAPIP(): 获取分配给SoftAP的IP地址。
  3. Serial类(用于调试):

    • Serial类用于在串口监视器上打印调试信息。
    • 成员函数:
      • begin(baud): 初始化串口通信,并指定波特率。
      • println(data): 将数据打印到串口监视器并换行。

这些API提供了在ESP32上设置和使用UDP通信所需的基本功能。通过这些函数,可以初始化UDP,发送和接收数据,处理连接,以及在串口监视器上输出调试信息。更详细的介绍请查看Arduino-ESP32手册

完整程序和测试效果


#include <Arduino.h>
#include <WiFi.h>

WiFiUDP udp;  //声明UDP对象,服务端开启,监听

void setup() {
  WiFi.softAP("ESP32_UDP","987654321");
  udp.begin(1133);
  Serial.begin(115200);
  //串口打印AP-IP
  Serial.println(WiFi.softAPIP());
}

void loop() {
  //接收发送过来的UDP数据
  if(udp.parsePacket()){
    char val=udp.read(); //读取一个字节
    Serial.println(val);
    
	//读取多个字节
    // char* val;
    // udp.read(val,255);
    // Serial.println(val);
    
    //将接收到的数据处理在回发
    udp.beginPacket(udp.remoteIP(),udp.remotePort());
    udp.println(val);
    udp.endPacket();
  }
}

串口发送且得到返回
在这里插入图片描述