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):
网络层 (Internet Layer):
传输层 (Transport Layer):
应用层 (Application Layer):
引入库文件: 引入必要的网络功能库文件<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地址和端口号。这三行代码一起完成了以下操作:
val
的值写入。这样,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] = '\0'; // 加上 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] = '\0';
来添加 null 终止符,使其适用于使用 Serial.println
打印。delete[] val;
来释放使用 new
分配的数组内存。请注意,在使用 new
动态分配内存后,必须使用 delete
或 delete[]
进行释放,以防止内存泄漏。
以下是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();
}
}
串口发送且得到返回