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 四层网络协议体系结构,用于指导互联网上数据的传输和通信。该模型的四个层次分别是:
-
链路层 (Link Layer):
- 功能:负责定义与物理网络介质的接口,处理通过该介质的原始比特流。该层通常包括设备驱动程序和网络接口卡 (NIC)。
- 协议:通常使用的协议包括以太网 (Ethernet)、Wi-Fi、PPP (Point-to-Point Protocol) 等。
-
网络层 (Internet Layer):
- 功能:负责在不同网络之间路由数据包,实现源到目标主机的数据传输。这一层的主要目标是确保数据从源主机传输到目标主机,即实现端到端的通信。
- 协议:主要协议是 Internet Protocol (IP),包括 IPv4 和 IPv6。
-
传输层 (Transport Layer):
- 功能:提供端到端的通信,负责数据的分段、重组和流量控制。该层主要确保数据在源和目标主机之间的可靠传输。
- 协议:主要协议包括 Transmission Control Protocol (TCP) 和 User Datagram Protocol (UDP)。
-
应用层 (Application Layer):
- 功能:提供网络服务和应用程序之间的接口,允许用户访问网络上的各种服务。这一层包含了各种应用层协议,支持不同的网络应用。
- 协议:包括常见的应用层协议如 Hypertext Transfer Protocol (HTTP)、File Transfer Protocol (FTP)、Simple Mail Transfer Protocol (SMTP) 等。
基本方法
ESP32的基本UDP设置流程:
-
引入库文件: 引入必要的网络功能库文件
<WiFi.h> 。#include <Arduino.h> #include <WiFi.h>
-
声明UDP对象: 使用
WiFiUDP 类声明一个UDP对象,该对象将用于处理UDP通信。WiFiUDP udp;
-
设置WiFi连接: 在
setup 函数中,配置ESP32的WiFi连接。将ESP32设置为SoftAP(访问点)模式,并指定SSID和密码。WiFi.softAP("ESP32_UDP", "987654321");
-
初始化UDP: 在
setup 函数中,使用udp.begin(port) 初始化UDP。这里的port 参数指定UDP服务器监听的端口号。udp.begin(1133);
-
串口打印IP地址(可选): 在
setup 函数中,可以使用Serial.println(WiFi.softAPIP()) 将分配给SoftAP的IP地址打印到串口监视器,以便调试和验证连接。Serial.println(WiFi.softAPIP());
-
处理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(); }
-
udp.beginPacket(udp.remoteIP(), udp.remotePort()); :beginPacket() 函数用于开始构建UDP数据包,指定了目标设备的IP地址和端口号。udp.remoteIP() 用于获取远程设备的IP地址。udp.remotePort() 用于获取远程设备的端口号。
-
udp.println(val); :println() 函数用于将数据写入UDP数据包。在这里,它将变量val 的值写入数据包。udp 对象是已经声明的WiFiUDP 对象,它管理UDP通信。
-
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 分配的数组内存。
请注意,在使用
常用API
以下是Arduino ESP32中涉及UDP通信的一些关键API的总结:
-
WiFiUDP类:
WiFiUDP 类用于处理UDP通信。- 成员函数:
begin(port) : 初始化UDP并指定监听的端口号。beginPacket(ip, port) : 打包一个UDP数据包准备将数据发送到指定的IP地址和端口。endPacket() : 结束UDP数据包,发送数据到指定的IP地址和端口。write(data, size) : 将指定大小的数据写入UDP数据包。parsePacket() : 检查是否有新的UDP数据包到达。read() : 读取一个字节的数据。remoteIP() : 获取远程设备的IP地址。remotePort() : 获取远程设备的端口号。
-
WiFi类:
WiFi 类用于处理ESP32的WiFi连接。- 成员函数:
softAP(ssid, password) : 将ESP32设置为SoftAP模式,并指定SSID和密码。softAPIP() : 获取分配给SoftAP的IP地址。
-
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(); } }
串口发送且得到返回